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