Как правильно и дешево идентифицировать массиво-подообные объекты?
Очевидно, что следующей проверки мало:
var array = [1];
var arrayLike = {0:1, length:1};
var fakeArrayLike = {length:1, height:2};
var window = window;
var fn = function() {};
alert(isArrayLike(array)); // true
alert(isArrayLike(arrayLike)); // true
alert(isArrayLike(fakeArrayLike)); // true | must be false
alert(isArrayLike(window)); // true | must be false
alert(isArrayLike(fn)); // false | must be false
// -------------------
/**
* @param {*} any
* @returns {Boolean}
*/
function isArrayLike(any) {
return isObject(any) && any.hasOwnProperty('length');
}
/**
* @param {*} any
* @returns {Boolean}
*/
function isObject(any) {
return any !== null && typeof any === 'object';
}
Тут написано, что эти объекты должны иметь метод splice, но по факту они его не имеют:
var collection = document.getElementsByTagName('body');
alert(collection.splice);
alert(collection.length);
ангуляр
/**
* @private
* @param {*} obj
* @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
* String ...)
*/
function isArrayLike(obj) {
if (obj == null || isWindow(obj)) {
return false;
}
var length = obj.length;
if (obj.nodeType === 1 && length) {
return true;
}
return isString(obj) || isArray(obj) || length === 0 ||
typeof length === 'number' && length > 0 && (length - 1) in obj;
}
жуквери
function isArraylike( obj ) {
var length = obj.length,
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
return false;
}
if ( obj.nodeType === 1 && length ) {
return true;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
Глядя на все это безобразие, кажется, что нет способа точно определить массиво-подобный объект. Так ли это?