JS-функция, переданная Array.prototype, рассматривается как свойство массива - PullRequest
1 голос
/ 11 октября 2011
Array.prototype.testi = function() {console.log('hep');}
var b = new Array();

b.push(1, 5, 'b', 'c');

for (var i in b) {
    console.log(b[i]);
}

Это будет регистрировать (в Chrome)

1
2
b
c
function () {console.log('hep');}

Или живой пример в http://jsfiddle.net/marqs/6VVka/1/

Мой вопрос, почему функция отображается в списке, хотяэто дано для прототипа массива?

Это имеет значение для расширения функций браузера, которые не используются (например, IE extended Array.filter будет вести себя иначе, если используется массив in и т. Д.).

Редактировать: чтобы уточнить, у меня нет доступа к коду, который выполняет цикл for-in, так как это внешняя библиотека.Таким образом, формулировка вопроса больше о том, «почему это так», чем о том, как это исправить.

Ответы [ 4 ]

2 голосов
/ 11 октября 2011

JavaScript объекты являются набором свойств. Внутри этих свойств есть свойства, которые описывают свойства. Главное, что вы здесь смотрите, это свойство [[Enumerable]], которое является мета-свойством, распространяющимся на большинство объектов по умолчанию в JavaScript, таких как Array и Object. ECMAScript 5 определяет метод добавления объектов, не относящихся к [[Enumerable]], но он не может широко поддерживаться в браузерах.

Один из способов запретить перечисление ненужных свойств объекта - проверить, есть ли у свойства объекта внутренний метод свойства с именем [[GetOwnProperty]]. Это гарантирует, что свойство было напрямую вызвано для объекта и НЕ унаследовано где-то в цепочке прототипов.

var arr = ['a','b','c'], indexes = [];
Array.prototype.each = function() {/*blah*/}; 

for (var index in arr) {
    if (arr.hasOwnProperty(index)) {
    indexes.push(index);
    }
}

indexes; //["0", "1", "2"]

Источник: http://javascriptweblog.wordpress.com/2011/01/04/exploring-javascript-for-in-loops/

2 голосов
/ 11 октября 2011

Цикл for-in зацикливает все унаследованные свойства объекта, а также его собственные свойства.В Ecmascript 5 есть способ скрыть ваши свойства от перечисления, см. Объекты и свойства Ecmascript 5 , но в IE это не работает.Рекомендуемый способ итерации массива заключается в использовании обычного цикла for:

for (var i = 0, len = b.length; i < len; i++)
    console.log(b[i])

Это также будет иметь гораздо лучшую производительность, чем цикл for-in, поскольку позволяет избежать поиска свойств объекта через прототип.цепь.Переменная len используется для кэширования длины массива, чтобы избежать ее поиска на каждой итерации цикла.Если вы хотите быть гладким, вы можете:

for (var i = b.length; i--;)
    console.log(b[i])

Это повторяет массив в обратном порядке и избегает дополнительной переменной len.

0 голосов
/ 11 октября 2011

Очевидно, Дуглас Крокфорд писал об этой же проблеме.

Недостаток в том, что оператор for in может перечислять ключи хранится в объекте, производит все ключи в объекте цепочка прототипов, а не только ключи в самом объекте. Это вызывает унаследованные методы появляются в перечислении, что плохо. Если бы было бы лучше, если бы JavaScript не содержал этот недостаток, но к счастью, мы можем программировать вокруг него.

http://yuiblog.com/blog/2006/09/26/for-in-intrigue/

0 голосов
/ 11 октября 2011

Любая вещь, которую вы добавляете в прототип объекта, будет появляться во всех экземплярах этого объекта.Вот как мы можем расширять объекты в JavaScript.

Пожалуйста, обратитесь к: http://phrogz.net/js/classes/ExtendingJavaScriptObjectsAndClasses.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...