Исправление функций массива JavaScript в Internet Explorer (indexOf, forEach и т. Д.) [Закрыто]

137

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

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

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

Ответы:

220

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

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

js-методы в целом выглядят нормально, но не так соответствуют стандартам, какими должны быть функции (например, неопределенные элементы списка, функции, которые изменяют список). Он также полон других случайных нестандартных методов, в том числе некоторых сомнительных, таких как хитрые 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, Objectметоды JSON и несколько новых методов, которые можно надежно реализовать как функции JS.

бобинс
источник
5
Спасибо за этот указатель - другие ссылки, которые я видел в mozdev, где можно было найти такие импы, устарели. К вашему сведению, код лицензирован MIT, как указано здесь: developer.mozilla.org/Project:Copyrights (примерно так же хорошо, как вы можете получить! :-)
cemerick
1
Интересно, что если я ссылаюсь на файл js, содержащий все подразумеваемые MDC ECMA262-5 до jquery 1.4.2, jquery не работает - например, все селекторы не работают, возвращая null. Перемещение MDC после jquery приводит к ожидаемому поведению. Очень странный.
цемерик
То есть любопытным! Посмотрим на это (у вас есть тестовый пример?) ... Я не могу сразу понять, почему это могло произойти, хотя то, что jQuery делает в строке 72, выглядит подозрительно.
bob
4
ПРИМЕЧАНИЕ: в большинстве браузеров, где нужны эти заглушки, если вы выполняете «for (index in somearray) {...}», вам нужно будет использовать somearray.hasOwnProperty (index) в качестве проверки. JS-движок IE <= 8 будет включать сюда расширения array.prototype. Асинхронный код Google Adwords этого не делает. Лучше всего использовать Underscore или другую библиотеку, которая стандартизирует это.
Tracker1
1
Это самая быстрая реализация indexOf () для IE 8, которую я смог найти. Благодарность!
Alex Denysenko
27

Взгляните на Underscore.js .

rfunduk
источник
2
ES5Shim и другие заглушки (например, от MDC) также имеют другие последствия. Для этих типов функций лучше всего использовать подчеркивание или другую библиотеку, которая будет использовать внутренние методы, если они доступны.
Tracker1
С Underscore.js var arr = ['a', 'a1', 'b'] _.filter (arr, function (a) {return a.indexOf ('a')> -1;})
sri_bb
9

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

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

Энди Э
источник
1

Под «не выполнять ключевые функции» вы на самом деле имеете в виду «соответствует 3-ей редакции ECMA 262», верно? :)

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

Шон Кинси
источник
1
Это хорошее начало, но есть немало ошибок в реализациях, не взятых из MDC. например. многие из методов массива не передают достаточное количество аргументов своим обратным вызовам и работают неправильно в случае изменения массива в функции обратного вызова.
bob
Я сделаю все, что смогу, чтобы сделать js более разумным / минимально совместимым языком. </snark> :-)
cemerick
1

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

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

Эгермано
источник
0

С Underscore.js

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

sri_bb
источник