JavaScript - Have you met [].slice.call() ?
Have you met [].slice.call(arguments)
or Array.prototype.slice.call(arguments)
in any JavaScript code?
This confusing code is used to convert the argument object which has .length
property and numeric indices (so-called array-like object) to a real Array, that invokes two methods: slice()
and call()
.
slice()
The
slice()
method returns a shallow copy of a portion of an array into a new array object selected frombegin
toend
(end
not included).Syntax:
arr.slice([begin[, end]])
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant']; console.log(animals.slice()); // [ 'ant', 'bison', 'camel', 'duck', 'elephant' ] console.log(animals.slice(2)); // ["camel", "duck", "elephant"] console.log(animals.slice(2, 3)); // [ 'camel' ]
see MDN web docs
call()
Both
call()
andapply()
methods let us manually set the value ofthis
.
Thecall()
method calls a function with a giventhis
value and arguments provided individually.Syntax:
func.call([thisArg[, arg1, arg2, ...argN]])
function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); this.category = 'food'; } console.log(new Food('cheese', 5).name); // cheese"
So, if we specify the value of this
in slice()
to an array-liked object,
we make slice()
method workable on the object, and if we call slice()
without passing optional arguments, it will return the whole chunk as a new array.
let listObj = {
'0': 'zero',
'1': 'one',
'2': 'two',
length: 3
};
let arr = [].slice.call(listObj);
console.log(arr); // [ 'zero', 'one', 'two' ]
As you can see, we could even convert the listObj
because the object has property length
and numeric indices.
In the end, there are other workarounds to convert an object to an array, here’s for your references.
Let’s say we have a NodeList object from a website, and we want to manipulate it like a real Array:
let links = document.querySelectorAll('.link');
let arr1 = [...links]; // iterable argument
let arr2 = Array.from(links);
let arr3 = [].slice.call(links); // [].slice === Array.prototype.slice;
let arr4 = Array.prototype.slice(links);
References
- Function.prototype.call() - MDN web docs
- how does Array.prototype.slice.call() work? - Stack Overflow