Некоторые вопросы о прототипе и массиве

Я нашел коды в книге и имел некоторые проблемы с этим.

var elems = {};
Array.prototype.push.call(elems, document.getElementById("first"));
alert(elems[0].nodeType); /It would output 1
  1. Я знаю, что "вызов" заключается в привязке метода push к объекту "elems". Но "элем" - это пустая объект, почему пустующий объект имеет метод "push"?
  2. Я попытался отбросить "прототип" из Array.prototype.push в Array.push. Но это не сработало. Зачем? Как я знаю из книги, этот метод будет найден из-за цепи прототипов. Благодарю.
2 ответа

Пример сеанса консоли, чтобы очистить все (прочитайте комментарии):

var elems = {};
Array.prototype.push.call(elems, 10); // you're telling 'push' to act like the argument is an array, even if it not
// that what 'call' does
> 1 // note that 'push' returns the length of the resultant array
elems
> Object {0: 10, length: 1} // 'push' is *acting* like 'elems' is an array, when really it not
> Array.prototype.push // getting from 'prototype' which is basically all the properties that every Array has
function push() { [native code] }
> Array.push // this doesn't exist
undefined
> [].push // shows the 'prototype' chain
function push() { [native code] }


У вашего объекта нет метода push. Используя .call(), вы инструктируете .push() работать с объектом, как если бы это был массив, который работает.

Array.push не работает (кроме Firefox), потому что .push - это метод, унаследованный для всех объектов Array. Таким образом, он существует в .prototype конструктора Array.

Если вы это сделали:

[].push.call(elems, ...)

он будет работать, потому что вы создаете новый массив и получаете .push() через наследование, которое поступает из Array.prototype.

В Firefox вам просто нужно сделать это:

Array.push(elems, document.getElementById("first"));

Это связано с тем, что Firefox имеет то, что он называет "Генераторы массива", которые принимают объект, для которого он должен работать в качестве первого аргумента, и элемент, который нужно нажать в качестве второго (или более).

licensed under cc by-sa 3.0 with attribution.