2014-01-16 2 views
1

Я добавляю полиграфию Array.indexOf() в основной файл JavaScript нашего проекта. Я взял его из devdocs.io:Как я могу предотвратить перечисление полиполков в JavaScript?

if (!Array.prototype.indexOf) { 
    Array.prototype.indexOf = function (searchElement , fromIndex) { 
    var i, 
     pivot = (fromIndex) ? fromIndex : 0, 
     length; 

    if (!this) { 
     throw new TypeError(); 
    } 

    length = this.length; 

    if (length === 0 || pivot >= length) { 
     return -1; 
    } 

    if (pivot < 0) { 
     pivot = length - Math.abs(pivot); 
    } 

    for (i = pivot; i < length; i++) { 
     if (this[i] === searchElement) { 
     return i; 
     } 
    } 
    return -1; 
    }; 
} 

мне это нужно, потому что мы по-прежнему должны поддерживать IE 8, но мне кажется, что в IE 8, функция IndexOf() добавляется перечислим. Это означает, что она появляется при переборе над массивами с помощью for..in петли, как это:

var a = []; 
a[0]=123; 
a[1]=456; 
for(var value in a) { 
    alert(value); // this even alerts "indexOf", if the polyfill above is loaded, and this is a big problem 
} 

Можно ли сделать polyfill «unenumerable», так что я могу использовать Array.indexOf() в IE 8, но он не появляется в цикле ... в петлях?

+7

Я думаю, что ... в ... это не очень хорошая идея с массивами: http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such -a-bad-idea –

+2

Решение здесь состоит в том, чтобы прекратить использование 'for ... in' для итерации массива. Вместо этого используйте простой цикл 'for'. –

+0

Я не могу изменить тот факт, что в нашем коде есть сотни для ... циклов над массивами. Было бы огромной работой по их изменению. Полипол, хотя, не был в коде так долго, и было бы относительно легко удалить его ... Если нет другого пути, мне придется это сделать. –

ответ

1

Вы должны использовать hasOwnProperty, когда вы перечислите элементы объекта.

var a = []; 
a[0] = 123; 
a[1] = 456; 
for(var value in a){ 
    if(a.hasOwnProperty(value)){ 
     alert(value); 
    } 
} 

Но почему вы не просто делаете простой for цикл (или что-то вроде polyfilling forEach)

+0

Для записи: опция jshint называется 'forin', чтобы предотвратить эту петлю без этой проверки. – Prinzhorn

+0

Смотрите мой комментарий выше. Мы не можем реализовать это для каждого цикла ... в нашем коде. Мне либо придется удалить полипол, либо сделать его невыполнимым. –

+0

Ну, во-первых, вы должны, вероятно, реорганизовать свою кодовую базу. Использование 'for ... in' для перечисления массивов - действительно плохая идея из-за перечислимых проблем. Во-вторых, вы можете. Он называется поиском и заменой с помощью регулярного выражения. :) – tkone

3

Вообще говоря, вы можете добавить свойство в несчетных с помощью Object.defineProperty:

Object.defineProperty(Array.prototytpe, 'indexOf', { 
    enumerable : false, 
    value : function(){ /* my polyfill code */} 
}); 

Но, как вы, наверное, догадались, в IE8 нет поддержки, поэтому вы застряли с решением @ tkone по фильтрации for..in с hasOwnProperty.


Другой псевдо-решение для создания функции вы передаете параметр массива в:

function indexOf(array, searchElement, fromIndex) { 
    if (Array.prototype.indexOf) return array.indexOf(searchElement, fromIndex); 
    /* my polyfill code with array instead of this*/ 
} 

и просто использовать, что вместо родного IndexOf:

[1,2,3].indexOf(2); // change to: 
indexOf([1,2,3], 2); 

Вы могли бы пространство имен ваша функция, так что вы не забудьте изменить ее на стандарты, когда вы больше не беспокоитесь о IE8:

IhateIE8.indexOf = ... 
0

Возможно ли, чтобы полиполк «unenumerable», так что я могу использовать Array.indexOf() в IE 8, но он не появляется в цикле for..in?

Официально да (см defineProperty и enumerable), но специально для IE8 и ниже, not really.

Я не думаю, что это хорошая идея (см. Комментарии).

Смежные вопросы