emre-ozgun
emre-ozgun

Reputation: 762

Reusing built-in array methods - JS - Confused

This is a piece of code that I couldn't reason about. These prototype array methods are used on elems object but I can't understand why length is affected by it. There is no array that has been defined whatsoever. Yet each add operation (via gather method) increments the 'length'. How does this object behave like an array ? Where are all these values stored in ? Can someone please shed some light on this ?

const elems = {
  length: 0,

  add: function(elem) {
    Array.prototype.push.call(this, elem);
  },
  gather: function(id) {
    this.add(document.getElementById(id))
  },
  find: function(callback) {
    return Array.prototype.find.call(this, callback);
  },
}

elems.gather('first');
console.log(elems.length === 1);

elems.gather('second');
console.log(elems.length === 2);

const found = elems.find((elem) => elem.id === 'second');
console.log(found.id === 'second');
<h1 id='first'>Hello</h1>
<h1 id='second'>Stack!</h1>

Upvotes: 0

Views: 73

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370839

Because the native .push method explicitly takes the length of the array-like object that it's called on, adds one to it, and assigns that result to the new .length property:

1. Let O be ? ToObject(this value).
2. Let len be ? LengthOfArrayLike(O).
3. Let argCount be the number of elements in items.
4. If len + argCount > 253 - 1, throw a TypeError exception.
5. For each element E of items, do
a. Perform ? Set(O, ! ToString(𝔽(len)), E, true).
b. Set len to len + 1.
6. Perform ? Set(O, "length", 𝔽(len), true).

Where are all these values stored in ?

On the length property of the object. It's not a hidden internal slot.

Upvotes: 2

Related Questions