Как исключить добавленные методы 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 раз или что-то в этом роде. Если вы сделаете некоторые измерения производительности, результаты будут интересны, поэтому, пожалуйста, поделитесь!:)