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 from begin to end (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() and apply() methods let us manually set the value of this.
    The call() method calls a function with a given this 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"
    

paragraph break

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

⤧  Previous post [Ruby] Clone, Dup 和 Shallow copy ⤧  Next post [JavaScript30] Day 08 - Canvas