javascriptarraysjavascript-objects

Why can Array.prototype methods be used with non-array objects?


Recently, I read an article that have the following lines

var obj = {};
Array.prototype.push.call(obj, 'aaa', 'bbb', 'ccc');
console.log(obj);
{0: "aaa", 1: "bbb", 2: "ccc", length: 3}

I know it tries to use obj as the context and passing the rest as the arguments. Before, I only used to push each item into an array. I am curious what is the logic behind this implementation. How it set index as each key of the value and why 'length' is automatically add to the object as well? thanks


Solution

  • Because that's how push works. Most array methods are intentionally generic so they can be applied to other objects, not only arrays.

    When the push method is called with zero or more arguments item1,item2, etc., the following steps are taken:

    1. Let O be the result of calling ToObject passing the this value as the argument.

    This just ensures that this is an object: var O = Object(this);

    1. Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".

    var lenVal = O.length;. lenVal will be undefined in our case, since the object doesn't have a length property.

    1. Let n be ToUint32(lenVal).

    Converts lenVal to a number and assigns the result to n. undefined will be converted to 0.

    1. Let items be an internal List whose elements are, in left to right order, the arguments that were passed to this function invocation.

    Basically var items = arguments;.

    1. Repeat, while items is not empty
      • Remove the first element from items and let E be the value of the element.
      • Call the [[Put]] internal method of O with arguments ToString(n), E, and true.
      • Increase n by 1.

    This simply iterates over all entries in items, assigns O[String(n)] = E; and n += 1. This is where each argument you pass to push is assigned to the object!

    1. Call the [[Put]] internal method of O with arguments "length", n, and true.

    Sets length to n: O.length = n;. This is where length is set!

    1. Return n.