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

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

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

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

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

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

Спасибо.


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

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

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

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

for (var prop in object)
{
  // Don't include properties inherited from the prototype chain
  if (object.hasOwnProperty(prop))
  {
    ...
  }
}

Ответ 4

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

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

Ответ 5

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

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

вместо:

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

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

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

Ответ 6

Изменить: исправлено неправильное использование типа из-за комментария @Bergi

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

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

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