Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

[].slice or Array.prototype.slice

I’v come across both ways to apply Array prototypes to a native object:

arr = Array.prototype.slice.call(obj);
arr = [].slice.call(obj);

In similar fashion, getting the true type of a native array-like object:

type = Object.prototype.toString.call(obj);
type = {}.toString.call(obj);

A simple test:

function fn() {
    console.log(
        Array.prototype.slice.call(arguments),
        [].slice.call(arguments),
        Object.prototype.toString.call(arguments), 
        {}.toString.call(arguments)
    );
}

fn(0,1);

Fiddle: http://jsfiddle.net/PhdmN/

They seem identical to me; the first syntax is used more often, but the second is definitely shorter. Are there any shortcomings when using the shorter syntax?

like image 580
David Hellsing Avatar asked Jan 25 '12 16:01

David Hellsing


People also ask

What is array prototype slice ()?

Array.prototype.slice() The slice() method returns a shallow copy of a portion of an array into a new array object selected from start to end ( end not included) where start and end represent the index of items in that array. The original array will not be modified.

Can we use slice for array?

The slice() method can be used to create a copy of an array or return a portion of an array. It is important to note that the slice() method does not alter the original array but instead creates a shallow copy.

What is the difference between array slice and splice?

Slice is used to get a new array from the original array whereas the splice is used to add/remove items in the original array. The changes are not reflected in the original array in the case of slice and in the splice, the changes are reflected in the original array.

Can slice () be used on strings and arrays?

Slice( ) and splice( ) methods are for arrays. The split( ) method is used for strings.


2 Answers

They are identical regarding functionality.

However, the Array object can be overwritten, causing the first method to fail.

//Example:
Array = {};
console.log(typeof Array.prototype.slice); // "undefined"
console.log(typeof [].slice);    // "function"

The literal method creates a new instance of Array (opposed to Array.prototype. method). Benchmark of both methods: http://jsperf.com/bbarr-new-array-vs-literal/3

When you're going to use the method many times, the best practice is to cache the method:

  • var slice = Array.prototype.slice; //Commonly used
  • var slice = [].slice; - If you're concerned about the existence of Array, or if you just like the shorter syntax.
like image 161
Rob W Avatar answered Sep 19 '22 09:09

Rob W


That's an interesting question! Let's pull up the pros (✔️) and cons (❌) for each alternative:

[].slice

  • ✔️: Is typed faster
    Two keystrokes, no shift-modifier or anything,
    and your linter knows [.slice is a typo.
  • ✔️: Is read faster
    You can identify the relevant part (slice) faster.
  • ✔️: Is more popular
    56M+ snippets on GitHub (as of late 2018).
  • ✔️: Can't be overwritten
    The first part of Rob's answer demonstrates this perfectly.
  • ✔️: Runs faster.
    Wait, what? Well, that's actually the whole point of this answer.

Contrary to what you'd think and read pretty much everywhere, [].slice.call(...) does NOT instantiate a new, empty Array just to access its slice property!.

Nowadays (it has been so for 5+ years – as of late 2018), the JIT compilation (1) is included everywhere you run JavaScript (unless you're still browsing the Web with IE8 or lower).

This mechanism allows the JS Engine to: (2)

... resolve [].slice directly, and statically, as direct Array.prototype reference in one shot, and just one configurable property access: forEach

Array.prototype.slice

  • ❌: Is typed slower
    Typos (e.g.: Array.prorotype.slice) look fine until you try and run the code.
  • ❌: Is less popular
    8M+ snippets on GitHub (as of late 2018).
  • ❌: Runs slower
    Array.prototype.slice is: (2)

... a lookup for the whole scope for an Array reference until all scopes are walked 'till the global one ... because you can name a variable Array any time you want.

Once the global scope is reached, and the native found, the engine accesses its proottype and after that its method
...
O(N) scope resolution + 2 properties access (.prototype and .forEach).

  • ✔️: Allows you to seamlessly adapt to whichever coding conventions would strictly prevent you from having a line start with either (, [ or `
    Definitely a good thing (sarcastically).
  • ✔️: You won't have to explain why [].slice is better in pretty much every way.
    Although now, that would just boil down to clicking the share link below 👌

Disclaimer

Note that, realistically, neither does effectively run faster than the other. This isn't the bottleneck of your application.


  1. You may want to read A crash course in just-in-time (JIT) compilers
  2. Quoted from Andrea Giammarchi (@WebReflection on Twitter)
like image 29
ccjmne Avatar answered Sep 20 '22 09:09

ccjmne