How to use the methods from other objects in JavaScript
Uriel
Posted on September 16, 2019
I recently ran into this lines of code in JavaScript:
[].slice.apply(arguments)
[].slice.call(document.querySelectorAll('foo'))
And although hard to read, this lines of code are so useful because they allow you to apple array specific methods to collections that not necessarily are arrays, such as NodeLists and the Arguments object.
But what are these lines of code doing and what can they tell us about the flexibility of JavaScript?.
The how
According with the W3Schools, the slice method allows you to select and copy elements from one array into a new array. So the first thing that came to my mind while reading this line of code [].slice.apply(arguments)
is, why are we calling slice in an empty array? If the purpose of this method is to select and copy elements from one array, how is it useful if we're calling it with an array that has no elements in it.
The thing is that this poor empty array is only exposing its precious slice method to be taken away. JavaScript allows you to change the context in which a method is called by using the apply and call methods. In other words, you can set the this
value in a method' body, through call and apply.
Remember that every JavaScript function is actually an Object, and a clear example of it is that every JavaScript function has a call and an apply method, among another handful of methods that you can call through the function definition.
In practical words, for every JavaScript function, you can call other methods such as apply and call, for example:
function foo(){}
foo.apply();
foo.call();
So what this line of code is doing [].slice.apply(arguments)
is that changes the context from the empty array, to the arguments object, to make it seem that the object that called slice
was arguments
and not the empty array itself.
What makes this work is that the arguments object has some properties that are similar to the ones that arrays have, such as length, and these similarities allows the slice method to work with both arguments and arrays as context.
After the first argument, the apply method allows you to send the arguments that will be passed as the arguments to the function call, in this case when calling the slice method, since in this case we're only passing one argument, the arguments object, the slice method receives no arguments, which according with the documentation means that all the array elements will be copied into the new array, which in resume means that this line of code copies all the elements from the arguments object into a new array.
Now, talking about readability, this methods does exactly the same that the Array.from
ES6 method does.
Array.from(arguments) === [].slice.apply(arguments)
The why
This particular line of code [].slice.apply(arguments)
allows us to easily convert an object that looks and possible behaves like an array but that is not array, another common example aside from the arguments object is the NodeList objects such as the ones returned from the querySelectorAll
function.
This is super useful because it allows us to play with the collection as an array, we can then plug the result into a loop, using it in combination with other array methods such as concat, includes, etc.
Conclusion
What this line of code let me thinking about after reading it, was in how JavaScript allows us to call methods from objects that do not posses these methods in its prototype, which I believe fits into the duck typing philosophy that languages such as Ruby have made so popular.
So, as long as an object can provide the properties and methods for a method to work, you can set this object as the context of the method to effectively call a method from an object that does not have that object.
So, what do you think of the way JavaScript works in these scenarios? Let me know in the comments.
I'd also appreciate if you can report grammar errors or typos to me since english ain't my native language. Thanks in advance!
Posted on September 16, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024