Исправление функций JavaScript-массива в Internet Explorer (indexOf, forEach и т.д.)

В качестве подробного в другом месте и, по-видимому, хорошо известного, Internet Explorer (определенно версия 7, а в некоторых случаях, версия 8) не реализует ключевые функции, в особенно на Array (например, forEach, indexOf и т.д.).

Существует несколько способов обхода проблемы, но я хотел бы добавить правильный, канонический набор реализаций на наш сайт, а не копировать и вставлять или взламывать наши собственные реализации. Я нашел js-methods, что выглядит многообещающе, но я подумал, что отправлю сюда, чтобы узнать, нужна ли еще одна библиотека более высоко. Несколько разных критериев:

  • Библиотека должна быть просто недействительной для тех функций, которые браузер уже имеет для реализации (js-methods выглядит здесь довольно хорошо).
  • Non- GPL, пожалуйста, хотя LGPL приемлемо.

Ответ 1

Многие используют резервные реализации MDC (например, для indexOf). Они, как правило, строго соответствуют стандартам, даже если они явно проверяют типы всех аргументов.

К сожалению, пока понятно, что авторы рассматривают этот код как тривиальный и свободно используемый, похоже, нет явного разрешения на предоставление лицензий, чтобы записать это в письменной форме. Вики в целом является CC Attribution-ShareAlike, если это приемлемая лицензия (хотя CC не предназначен для кода как такового).

js-методы выглядят нормально вообще, но не соответствуют стандартам по краям того, как должны функционировать функции (например, undefined элементы списка, функции, которые мутируют список). Он также полон других случайных нестандартных методов, включая некоторые сомнительные, такие как изворотливые stripTags и неполный кодек UTF-8 (что также немного не нужно, учитывая трюк unescape(encodeURIComponent)).

Для чего это стоит, здесь то, что я использую (которое я тем самым выпускаю в общественное достояние, если можно сказать, что оно полностью защищено авторскими правами). Это немного короче, чем версии MDC, так как он не пытается набирать текст, чтобы вы не делали что-то глупое, как пропускать неработающие обратные вызовы или нецелые индексы, но кроме этого он пытается соответствовать стандартам. (Дайте мне знать, если я пропустил что-нибудь. -))

'use strict';

// Add ECMA262-5 method binding if not supported natively
//
if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        if (arguments.length<=1) {
            return function() {
                return that.apply(owner, arguments);
            };
        } else {
            var args= Array.prototype.slice.call(arguments, 1);
            return function() {
                return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
            };
        }
    };
}

// Add ECMA262-5 string trim if not supported natively
//
if (!('trim' in String.prototype)) {
    String.prototype.trim= function() {
        return this.replace(/^\s+/, '').replace(/\s+$/, '');
    };
}

// Add ECMA262-5 Array methods if not supported natively
//
if (!('indexOf' in Array.prototype)) {
    Array.prototype.indexOf= function(find, i /*opt*/) {
        if (i===undefined) i= 0;
        if (i<0) i+= this.length;
        if (i<0) i= 0;
        for (var n= this.length; i<n; i++)
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('lastIndexOf' in Array.prototype)) {
    Array.prototype.lastIndexOf= function(find, i /*opt*/) {
        if (i===undefined) i= this.length-1;
        if (i<0) i+= this.length;
        if (i>this.length-1) i= this.length-1;
        for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('forEach' in Array.prototype)) {
    Array.prototype.forEach= function(action, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                action.call(that, this[i], i, this);
    };
}
if (!('map' in Array.prototype)) {
    Array.prototype.map= function(mapper, that /*opt*/) {
        var other= new Array(this.length);
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                other[i]= mapper.call(that, this[i], i, this);
        return other;
    };
}
if (!('filter' in Array.prototype)) {
    Array.prototype.filter= function(filter, that /*opt*/) {
        var other= [], v;
        for (var i=0, n= this.length; i<n; i++)
            if (i in this && filter.call(that, v= this[i], i, this))
                other.push(v);
        return other;
    };
}
if (!('every' in Array.prototype)) {
    Array.prototype.every= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && !tester.call(that, this[i], i, this))
                return false;
        return true;
    };
}
if (!('some' in Array.prototype)) {
    Array.prototype.some= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && tester.call(that, this[i], i, this))
                return true;
        return false;
    };
}

Другие методы ECMA262-5, не реализованные здесь, включают Array reduce/reduceRight, JSON и несколько новых методов Object, которые могут быть надежно реализованы как функции JS.

Ответ 3

Kris Kowal собрал небольшую библиотеку, которая действует как прокладка для функций ECMAScript 5, которые могут отсутствовать в реализации браузера. Некоторые из функций были неоднократно пересмотрены другими людьми для оптимизации скорости и для работы с ошибками браузера. Функции записываются так, чтобы они соответствовали спецификации как можно ближе.

es5-shim.js был выпущен под лицензией MIT, расширения Array.prototype находятся в верхней части, и вы можете нарезать и удалить любые функции вам не нужно довольно легко. Я также предлагаю вам минимизировать script, поскольку комментарии делают его намного больше, чем нужно.

Ответ 4

"Не реализуйте ключевые функции", вы на самом деле означает "соответствует требованиям ECMA 262 3'rd ed"?:)

Методы, о которых вы говорите, являются частью нового 5-го издания - для браузеров, которые не поддерживают это, вы можете использовать следующую "прокладку", которая расширяет 3'-й до 5-го http://github.com/kriskowal/narwhal-lib/blob/narwhal-lib/lib/global-es5.js.

Ответ 5

Эти сценарии не работают хорошо в моих тестах. Я создаю файл с теми же функциями на основе документов MDN.

Слишком много проблем разрешены в Internet Explorer 8. См. Код в egermano/ie-fix.js.

Ответ 6

С помощью Underscore.js

var arr=['a','a1','b'] _.filter(arr, function(a){ return a.indexOf('a') > -1; })