Further discussion of this topic on es-discuss has convinced its original proposer, MarkM, that there is no coherent general convention for isArrayLike that can be rescued and reconciled with existing practice. Accordingly, I have stopped editing this page. If someone does believe that attempting a coherent proposal would still be productive, they should please edit this page accordingly. —MarkM 1/9/2010 10:48am PDT
This es-discuss thread documents a variety of conventions currently in use to determine if an object should be array-like. The following proposed predicate has the virtues that it
function isArrayLike(obj) { return !!(obj && typeof obj === 'object' && 'length' in obj && !({}.propertyIsEnumerable.call(obj, 'length')); }
({}).toString.call(obj) !== '[object String]'
conjunct.
obj is a non-host object, it can cause side effects when obj is a proxy. This is necessary to allow proxies to emulate array-like objects adequately to pass the above predicate.propertyIsEnumerable test above, despite the name, actually tests whether a property is both enumerable and own. This means the above predicate will reject objects that inherit a non-enumerable length property. I can think of no reliable and portable ES3R test which tests only property enumerability, except by running a for-in loop and testing the output. Doing so would kill the bounded-by-constant time virtue.