2011-01-25 4 views
2
Array.prototype.last = function() { if(this.length !=0) return this[this.length-1]; } 
myarray = new Array(1,2,3); 
    for(var i in myarray){ 
    alert(i+'='+myarray[i]); 
} 

Когда выше код выполняется, это правильно оповещает каждый цикл, но затем в конце другого предупреждение всплывает с источником метода Array.prototype.last.JS прототип возвращает код прототипа

Это происходит, когда я определяю какой-либо прототип метода, и я просто не знаю почему!

Так я получаю уведомления для: 0 = 1,1 = 2,2 = 3, а затем один за:

last=function() { 
    if (this.length != 0) { 
    return this[this.length - 1]; 
    } 
} 

ответ

6

Это потому, что for-in оператор перечисляет свойства объектов, включенных наследуемые из них.

Это одна из причин, почему использование оператора for-in с массивами или объектов массива считается плохой практикой.

Другие причины включают в себя, что порядок перечисления не гарантируется спецификацией, это означает, что свойства индекса не может быть посещены в числовом порядке, например:

var a = []; 
a[1] = 'b'; 
a[0] = 'a' 

for (var prop in a) { console.log(i); } 

Большинство браузеров обнаружит вас пытаясь перебрать над массивом, и свойства будут посещаться в числовом порядке, но в IE свойства будут перечислены в том порядке, в котором они были созданы, 1, а затем 0.

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

В качестве общей рекомендации всегда используйте последовательный цикл до итерации такого рода объектов.

Смотрите также:

+0

Ааа, ну я думаю, это очевидно, когда вы знаете, но я нахожу для (вар в массиве), чтобы быть быстрее, чтобы написать, чем для (вар я = 0; я crankshaft

+0

@Crankshaft: вы можете использовать jQuery $ .each() i.e $ .each (myarray, function (index, value) {alert (value);}), чтобы избежать этой проблемы. – dhinesh

0

Вот почему вы никогда не использовать for(idx in anArray){...} в JavaScript в для ... в итерацию цикла более все свойства в object, и Array это всего лишь object в JS, вы добавили новое свойство ко всем экземплярам Array, чтобы он отображался как один из индексов в цикле for.

с массивами, как правило, вы должны сделать:

for(var i=0 ; i< anArray.length ; i++){ 
    //do stuff 
} 
+0

Чтобы быть более точным, он добавил свойство прототипу Array, которое перечислимо и унаследовано каждым экземпляром Array. Немного разъяснения между этим и «добавление свойства в каждый экземпляр». –

+0

@ Ken, есть ли? Подумайте об этом таким образом, добавив его в прототип, это свойство недоступно из всех существующих и будущих экземпляров 'Array'? Семантика прототипов в JS такова, что я не считаю это утверждение неправильным или вводящим в заблуждение. – tobyodavies

+0

Когда я впервые прочитал «новое свойство для всех экземпляров массива», я увидел потенциальную двусмысленность, например. между каждым экземпляром, фактически имеющим свою собственную копию значения, по сравнению с наследованием от одного общего места. Не все понимают, как работают прототипы, поэтому мне не нравится оставлять место для (неправильной) интерпретации;) Вы, очевидно, знали, о чем говорите, но не каждый мог бы почерпнуть это из вашей первоначальной формулировки. «Sallimsayin. –

0

Это потому, что последняя является функцией, которая MyArray вытекает из свойств прототипа и индексируется. Чтобы избежать этого, вам нужно проверить hasOwnProperty именно:

for(var i in myarray) 
{ 
    if(myarray.hasOwnProperty(i)) 
    alert(i+'='+myarray[i]); 
} 
+0

+1 для правильного объяснения наследования и перечислимости прототипа и hasOwnProperty, но все же лучше всего избегать ... in для итерации массива. –

+0

@Ken: Спасибо. Согласовано. @Someone: Мне любопытно узнать причину downvote. – Chandu

+1

Возможно, они думали, что я слишком щедрый, учитывая продолжение использования для массивов. знак равно –