Как исключить добавленные методы Array из обработки в цикле "for..in"? (JavaScript) - PullRequest
1 голос
/ 27 ноября 2009

Я добавил несколько полезных помощников в Array (например, toSource() для Opera). И теперь for..in возвращает функции с обычными свойствами.

Я использую for..in сейчас, потому что код легче читать с ним. И это нативный функционал js, поэтому должен быть быстрее.

Но добавление проверок типов в цикле облегчает использование классических for(;;).

Есть ли способы, чтобы избежать for..in перечисления функций?

Кросс-браузерная работа не очень нужна (должна работать в Opera), но важна скорость.

Спасибо.


Edit:
Есть ли возможность избежать for..in перечисления функций или пользовательских свойств любого объекта?

Ответы [ 6 ]

5 голосов
/ 27 ноября 2009

Вы должны никогда использовать циклы for..in для перебора элементов массива. for..in предназначен для итерации по свойствам и должен использоваться только для этого по той причине, которую вы только что описали. Многие библиотеки модифицируют прототипы массивов, дат и т. Д., Поэтому вам не следует полагаться на… при переборе только элементов массива. Используйте метод for (;;), он гарантированно сделает то, что вы хотите. И это не быстрее, чем цикл for..in, потому что он также является родным для javascript.

Подробнее об этом читайте в библиотеке prototype.js .

3 голосов
/ 27 ноября 2009

Да, но это JavaScript 1.7+ - только. Opera имеет только ограниченную поддержку JavaScript 1.7, которая включает в себя базовую поддержку назначения деструктурирования, поэтому это не будет работать в Opera, но будет работать в Firefox.

Эта реализация позволяет безопасно использовать for [each](item in array):

Array.prototype.__iterator__ = function (flag) {
    var len = this.length, i = 0;

    for (; i < len; i++) {
        yield flag ? i : this[i];
    }
};
2 голосов
/ 04 января 2012

Существует еще одна опция с поддержкой ES5, которая позволяет вам определять не перечисляемые свойства! Должно быть возможно (хотя я не проверял) сделать что-то вроде этого:

Object.defineProperty( Array.prototype, "myNewMethod", {
   value: function(){},
   writable: true,
   enumerable: false, /* this controls for..in visibility */
   configurable: true
});
2 голосов
/ 27 ноября 2009

Как уже говорили другие, вы не должны использовать for..in для перебора массивов. Это медленнее, чем использование for (;;).

Вам также следует кэшировать длину массива, если вас интересует производительность, например:

for (var i=0, len=arr.length; i<len; i++) 
{
  ... 
}

Используйте только for..in для перебора свойств объектов. Чтобы исключить унаследованные свойства, используйте метод hasOwnProperty ():

for (var prop in object)
{
  // Don't include properties inherited from the prototype chain
  if (object.hasOwnProperty(prop))
  {
    ...
  }
}
1 голос
/ 27 ноября 2009

То, что вы описываете, именно поэтому вы используете

for (var i=0; i<arr.length; i++) { ... }

вместо:

for (var item in arr) { ... }

потому что они разные.

Если вам не нужны все элементы, которые вы получите во второй форме, и только индексированные элементы, тогда используйте первую форму.

0 голосов
/ 06 декабря 2009

Редактировать: исправлено неправильное использование типа благодаря комментарию @Bergi

Хорошие замечания по поводу производительности при переборе (очень) разреженных массивов - я бы предположил, что, возможно, использование isNaN (parseInt ()) в цикле позволит вам найти только элементы массива:

for( var propertyName in myArray){
    if( !isNaN(parseInt(propertyName)) ){ /* probably array element */ }
}

Я не знаю, что работает лучше в hasOwnProperty () и вышеупомянутом подходе. Вы просто должны измерить это с очень большим массивом, повторяя его 10000 раз или что-то в этом роде. Если вы сделаете некоторые измерения производительности, результаты будут интересны, поэтому, пожалуйста, поделитесь! :)

...