Как определить, является ли переменная массивом



каков наилучший де-факто стандартный кросс-браузерный метод для определения того, является ли переменная в JavaScript массивом или нет?



поиск в интернете есть ряд различных предложений, некоторые хорошие и довольно много недействительных.



например, следующий базовый подход:



function isArray(obj) {
return (obj && obj.length);
}


однако обратите внимание, что происходит, если массив пуст, или obj на самом деле не является массивом, но реализует свойство length и т. д.



Так что реализация является ли лучшим с точки зрения реальной работы, будучи кросс-браузером и по-прежнему эффективно работать?

555   12  

12 ответов:

проверка типов объектов в JS выполняется через instanceof, т. е.

obj instanceof Array

это не будет работать, если объект передается через границы кадра, а каждый кадр имеет свою собственную

прибытие ECMAScript 5th Edition дает нам самый надежный метод тестирования, если переменная является массивом,массив.isArray ():

Array.isArray([]); // true

в то время как принятый ответ здесь будет работать через рамы и окна для большинства браузеров, это не для Internet Explorer 7 и ниже, потому что Object.prototype.toString вызов массива из другого окна вернет [object Object], а не [object Array]. IE 9, похоже, также регрессировал к этому поведению (см. обновленное исправление ниже).

Я не буду вдаваться во все мелкие детали решения здесь, Если вы заинтересованы в том, что вы можете прочитать этот блог. Однако, если вы хотите решение, которое работает во всех браузерах, вы можете использовать:

(function () {
    var toString = Object.prototype.toString,
        strArray = Array.toString(),
        jscript  = /*@cc_on @_jscript_version @*/ +0;

    // jscript will be 0 for browsers other than IE
    if (!jscript) {
        Array.isArray = Array.isArray || function (obj) {
            return toString.call(obj) == "[object Array]";
        }
    }
    else {
        Array.isArray = function (obj) {
            return "constructor" in obj && String(obj.constructor) == strArray;
        }
    }
})();

Он не совсем нерушим, но он будет сломан только тем, кто изо всех сил пытается его сломать. Он работает вокруг проблем в IE7 и ниже и IE9. ошибка все еще существует в IE 10 PP2, но это может быть исправлено до релиза.

PS, Если вы не уверены в решении, то я рекомендую вам проверить его на содержание вашего сердца и/или прочитать сообщение в блоге. Есть и другие потенциальные решения, если вам неудобно использовать условную компиляцию.

Крокфорд имеет два ответа на странице 106 "хорошие части."Первый проверяет конструктор, но даст ложные негативы в разных кадрах или окнах. Вот второй:

if (my_value && typeof my_value === 'object' &&
        typeof my_value.length === 'number' &&
        !(my_value.propertyIsEnumerable('length')) {
    // my_value is truly an array!
}

Крокфорд указывает, что эта версия будет идентифицировать arguments массив как массив, даже если он не имеет ни одного из методов массива.

есть еще интересная дискуссия (пост-хорошие части)здесь который включает в себя это предложение:

var isArray = function (o) {
    return (o instanceof Array) ||
        (Object.prototype.toString.apply(o) === '[object Array]');
};

все обсуждение заставляет меня никогда не хотеть знать, является ли что-то массивом.

jQuery реализует функцию isArray, которая предлагает лучший способ сделать это

function isArray( obj ) {
    return toString.call(obj) === "[object Array]";
}

(фрагмент взят из jQuery v1.3. 2 - слегка скорректирован, чтобы иметь смысл вне контекста)

кража у гуру Джона отставки и jquery:

function isArray(array) {
    if ( toString.call(array) === "[object Array]") {
        return true;
    } else if ( typeof array.length === "number" ) {
        return true;
    }
    return false;
}

что вы собираетесь делать со значением, как только вы решите, что это массив?

например, если вы собираетесь перечислить содержащиеся значения, если это выглядит как массив или если это объект, используемый в качестве хэш-таблицы, то следующий код получает то, что вы хотите (этот код останавливается, когда функция закрытия возвращает что-либо, кроме "undefined". Обратите внимание, что он не выполняет итерацию по COM-контейнерам или перечислениям; это остается в качестве упражнения для читатель):

function iteratei( o, closure )
{
    if( o != null && o.hasOwnProperty )
    {
        for( var ix in seq )
        {
            var ret = closure.call( this, ix, o[ix] );
            if( undefined !== ret )
                return ret;
        }
    }
    return undefined;
}

(Примечание: "o != null " тесты для обоих null & undefined)

пример использования:

// Find first element who's value equals "what" in an array
var b = iteratei( ["who", "what", "when" "where"],
    function( ix, v )
    {
        return v == "what" ? true : undefined;
    });

// Iterate over only this objects' properties, not the prototypes'
function iterateiOwnProperties( o, closure )
{
    return iteratei( o, function(ix,v)
    {
        if( o.hasOwnProperty(ix) )
        {
            return closure.call( this, ix, o[ix] );
        }
    })
}

Если вы хотите кросс-браузер, вы хотите jQuery.isArray.

On w3school есть пример, который должен быть вполне стандартным.

чтобы проверить, является ли переменная массивом, они используют что-то похожее на это

function arrayCheck(obj) { 
    return obj && (obj.constructor==Array);
}

протестировано на Chrome, Firefox, Safari, ie7

если вы делаете это в CouchDB (SpiderMonkey), то используйте

Array.isArray(array)

как array.constructor === Array или array instanceof Array не работают. Используя array.toString() === "[object Array]" работает, но, кажется, довольно сомнительный в сравнении.

один из лучших исследованных и обсуждаемых вариантов этой функции можно найти на сайт PHPJS. Вы можете ссылаться на пакеты, или вы можете перейти к напрямую. Я настоятельно рекомендую сайт для хорошо построенных эквивалентов функций PHP в JavaScript.

недостаточно ссылок, равных конструкторам. Иногда они имеют разные ссылки конструктора. Поэтому я использую их строковые представления.

function isArray(o) {
    return o.constructor.toString() === [].constructor.toString();
}

заменить Array.isArray(obj) by obj.constructor==Array

примеры :

Array('44','55').constructor==Array return true (IE8 / Chrome)

'55'.constructor==Array return false (IE8 / Chrome)

Comments

    Ничего не найдено.