Виправлення функцій масиву JavaScript в Internet Explorer (indexOf, forEach тощо) [закрито]


137

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

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

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

Відповіді:


220

Багато хто використовує резервні реалізації MDC (наприклад, для indexOf ). Вони, як правило, суворо відповідають стандартам, навіть настільки чітко перевіряючи типи всіх аргументів.

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

js-методи загалом виглядають нормально, але вони не є наближеними до стандартів по краях того, як мають бути функції (наприклад, невизначені елементи списку, функції, що мутують список). Також багато інших випадкових нестандартних методів, включаючи деякі сумнівні, такі як хитрі стриптиз-теги та неповний кодек 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, не реалізовані тут, включають масив reduce/ reduceRight, JSON та кілька нових Objectметодів, які можна надійно реалізувати як функції JS.


5
Дякую за цей покажчик - інші посилання, які я бачив у mozdev, де такі імпульси можуть бути знайдені, були несвіжими. FYI, код має ліцензію на MIT, як зазначено тут: developer.mozilla.org/Project:Copyrights (приблизно так добре, як ви можете отримати! :-)
cemerick

1
Цікаво, що якщо я посилаю на js-файл, що містить усі імпульси MDC ECMA262-5 перед jquery 1.4.2, jquery порушується - наприклад, всі селектори виходять з ладу, повертаючи null. Переміщення імпульсів MDC після jquery призводить до очікуваної поведінки. Дуже дивно.
cemerick

Це є цікавим! Подивіться на це (у вас є тестовий випадок?) ... Я не можу відразу подумати, чому це може статися, хоча те, що робить jQuery у рядку 72, виглядає підозрілим.
bobince

4
ПРИМІТКА: у більшості веб-переглядачів, де потрібні ці заглушки, якщо ви робите "для (індекс у деякомумасі) {...}", вам потрібно буде використати somearray.hasOwnProperty (index) як чек. Двигун JS IE <= 8 включить до цього розширення array.prototype. Код асинхронізації Google Adwords не робить цього. Найкраще використовувати підкреслення або іншу функціональність бібліотеки, яка стандартизується на цьому.
Tracker1

1
Це найшвидша реалізація indexOf () для IE 8, яку я міг знайти. Дякую!
Олексій Денисенко

27

Погляньте на Underscore.js .


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

Під "не реалізувати ключові функції" ви фактично маєте на увазі "відповідність ECMA 262 3-й ед", правильно? :)

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


1
Це вдалий початок, але є досить багато помилок у впровадженні, не взяті з MDC. напр. багато методів масиву не передають достатньо аргументів своїм зворотним викликам і не діють досить правильно у випадку мутації масиву у функції зворотного виклику.
bobince

Я візьму все, що можу, щоб зробити 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; })

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.