Как исключить добавленные методы Array из обработки в цикле "for..in"? (JavaScript)

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

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

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

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

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

Спасибо.


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

6 ответов

Решение

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

Для получения дополнительной информации читайте об этом в библиотеке prototype.js.

Да, но это 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];
    }
};

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

Object.defineProperty( Array.prototype, "myNewMethod", {
   value: function(){},
   writable: true,
   enumerable: false, /* this controls for..in visibility */
   configurable: true
});

Как уже говорили другие, вы не должны использовать 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))
  {
    ...
  }
}

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

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

вместо:

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

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

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

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

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

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

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

Другие вопросы по тегам