Nothing really surprising, just a property of an object. Another way to add elements to an array, is to use the
.push method, which takes an element and appends it to the end of the array.
Both methods are going to increase the special
.length property of the array, which stores how many elements there are in the collection.
So arrays are objects. Would it be possible to use Array methods onto normal objects? Yes, sir. The really common example is, the magical
arguments variable that is silently passed in all function calls:
It looks like an array, it kinda works like an array, but it's really only a array-like object. Array methods won't work on it. The following code won't work
First of all, Array methods are defined in its prototype, I won't get into details about it here, as it is a long topic, but in case you don't know, think of it as a shared property where all Array objects have their methods defined.
So, a quick example
Believe me, they are all there. What happens is, when a method is called in an Array, its context, in other words, the
this keyword inside the function is set as the object instance, the
var a in the examples.
"So they are the same function, can we call the
Array.prototype.push directly?". Yes, but don't. Bad things will happen.
.push method directly will set the context as the object itself, the
Array.prototype object to be exact. So it'll be adding elements to the prototype of the Array, don't do that, it's not cool, bro.
"Okay, how is this useful, then?" Let's quickly talk about
These are methods that are defined inside the
Function prototype object. Yep, functions are first-class citizens. The cool thing about them, is that they allow the definition of the context in which the function is being called, in other words, it's possible to define the value of
The difference between
.apply is the type of their arguments. The first one is the context for both, all others are the arguments that are going to be passed to the function itself. And the difference is that
.call receives a list of arguments, and
.apply receives an array of arguments. Fear not! See the example:
Going back to the
arguments as an Array issue, the usual way to solve this is to call the
.slice method from the Array prototype, which duplicates the result, leaving the original object intact. It is possible to directly call the Array method passing the
arguments as its context too.
After this theory, let's talk about what this article is about..
fooling the Array
So we learned about Arrays methods and how to call them on different objects. But how do they actually work? What does the methods take into consideration? Let's fool
It's possible to check that:
objis still an Object, but not an Array
.lengthproperty was added to
- a key valued pair is added each time, where the key is the current
.lengthof the object when the method was called
So what happens if we manipulate the values?
We can see that the
.length property is taken into consideration and the previous values end up being overwritten because they happen to have the same key. With these tests, it's possible to especulate that the code for
.push method is something like
I bet there are many cases not being covered in the implementation, but that's the bigger picture. A new property is created were the key is the value of
.length and the value is the argument itself, and
.length is incremented.
Why would somebody use that? I don't know. It's not quite foolling the
.push method, that's more like fooling ourselves. But it's just cool to realize how stuff works and how you can use methods from other objects. The dolphin eventually appears when we know this stuff.