Use Array Prototype Functions with non-arrays

2019-08-09 03:50发布

问题:

As we know we can use Array prototype methods with function arguments just like below.

function abc() {
   // As 'arguments' is a array like object which don't have Array prototype functions.
   Array.prototype.push.call(arguments, 30);
   console.log(arguments);
}
abc(10, 20);   // Output is: [10, 20, 30]

So like wise I tried to use push on DOM element classList like below which gives me an error "Cannot set property length of [object Object] which has only a getter".

var bodyClassList = document.body.classList;
Array.prototype.push.call(bodyClassList, 'myClass');

Note: I have just tried to learn concepts so that's why I used push even it has builtin add() method.

So my question is:

On which objects we can use Array.prototype methods?

Thanks in advance.

回答1:

Array.prototype methods are quite generic methods that work on all kinds of objects. They're just getting and setting indexed properties and the .length of the object they are called on. (And, with ES6, the .constructor property of Array instances if they need to create a new instance). You can check the spec to see what push does exactly.

So basically, to answer your question…

On which objects we can use Array.prototype methods?

…on all objects. That is, objects that don't throw exceptions when they are being operated on. Notice that push itself does not throw the error.

Some examples:

var x = {0:0, length:1};
Array.prototype.push.call(x, 1);
console.log(x); // {0:0, 1:1, length:2}
console.log(Array.prototype.slice.call(x)); // [0, 1]
var y = {0:0, get length() { throw new Error("boo!"); }}
Array.prototype.push.call(y, 1); // throws
var z = {get 0() { throw new Error("boo!"); }, length: 1};
Array.prototype.push.call(z, 1);
console.log(z); // {0:…, 1:1, length:2}
console.log(Array.prototype.slice.call(z)); // throws

The arguments object is very much like x. The classList is very much like y.