The approach of using obj.join
is sometimes called "duck-typing". Using join
as you propose will fail miserably if you use it on an object which happens to contain a join
property.
Just use the APIs which are designed for the task, such as Array.isArray
, or a routine from a utility library. They have already thought through all of the issues. For example, Underscore uses Object.prototype.toString.call(obj) === '[object Array]'
. There is also an extensive literature right here on SO on the topic, starting with the one you mention.
The more basic question is, why do you have things and don't know whether they are arrays or not? Perhaps some utility routines for traversing arbitrary objects might need to check for array-ness, or a server might send down something that might or might not be an array, but a well designed user-program should already know which objects are what. To put it a different way, if you were ever to move to a typed approach such as TypeScript, what type would you propose to assign to these maybe-an-array-maybe-not objects? Would you use any
, which sort of defeats the whole purpose?
The second question is, why are you obsessing over a few microseconds? Do you have a game which is recalculating the position of hundreds of thousands of objects, sixty times per second? If not, it doesn't matter. If it does matter, see previous paragraph, and refactor your code so as not to have to check for something being an array all the time.
By the way, a meaningful benchmark should be run a million times. FWIW, console.time[End]
often comes in handy for quick-and-dirty benchmarks. Anyway, according to your fiddle, the time difference is nothing more than a factor 1.5 or so at worst.
Minor note: Array === obj.constructor
is not going to play well with subclasses of Array
.