0

Just wondering what's the different with the following js script.

[].slice.call(this) vs Array.prototype.slice.call(this);

They seems to be doing this same, can someone explain the different and which one i should stick with?

Cheers

6
  • It seems you have a typo; Array, not array, right? Commented Dec 5, 2014 at 1:09
  • 1
    Array.prototype.call is incorrect. Maybe you meant Array.prototype.slice.call() ? Commented Dec 5, 2014 at 1:11
  • sorry i miss the slice out Commented Dec 5, 2014 at 1:16
  • Since it wasn't mentioned explicitly: Array.prototype.slice === [].slice. It's the same function, just two different ways to get a reference to it. Commented Dec 5, 2014 at 4:24
  • 1
    BTW, the modern (and intuitively understandable) ES6 method for the same is Array.from. Commented Apr 27, 2019 at 14:11

4 Answers 4

2

They are almost identical. Let's examine each of them:

[].slice.call(data)

What it does?

  • [] - this creates new Array, same to new Array()
  • slice - it retrieves method slice from array
  • call(data) - it calls slice() method replacing its current context with data variable, i.e. uses data as its internal array, not []. This returns our data converted into Array.

Now, the second one:

Array.prototype.slice.call(data)

This one:

  • Array.prototype.slice - retrieves method slice from Array.prototype; in a nutshell - it returns you slice method without any context (internal data).
  • call(data) - as in previous variant, calls this method with data as its context.

Conclusion

Both [].slice and Array.prototype.slice return you a slice function which you can call on some array, however this array is passed not as argument, but as context (using call method of function object). In JavaScript, these calls will be absolutely the same:

// Calling as a method of 'Hello' string
'Hello'.indexOf('e') // returns 1

// Calling as unbound method
String.prototype.indexOf.call('Hello', 'e') // returns 1
String.prototype.indexOf.apply('Hello', ['e']) // returns 1

Those methods are almost the same. First one is more readable, but second one uses a bit less memory because it isn't creating a temporary initial Array.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks Andrew this make sense a lot
@bluebill1049 another interesting addition: if you call [].slice(), it will return an empty array [], and if you do [1,2,3].slice(), [1,2,3] will be returned. And, on the other hand, calling Array.prototype.slice() directly (without .call) will always return [] because it has no internal context, it's smth like "static metod".
nice example :) second one is better
@AndrewDunai I just wanted to stress the fact that slice always returns a new array. So calling slice is an array construction as well. Also the memory usage is not really the crux here but the CPU time to construct and garbage collect these arrays can be problematic in high performance applications.
"calling Array.prototype.slice() directly ... will always return [] because it has no internal context" That's not exactly true. In that case, this will refer to Array.prototype. And it so happens that Array.prototype.length is 0. That's why you get an empty array.
|
1

I believe that Array doesn't actually create an object, where as [] is an instance of Array.

Comments

1

Definitely stick with the latter one as the first one is an implicit array construction and the same as:

new Array().slice.call(this)

Its constructing a new array that needs to be garbage collected afterwards since you dont use it. While both statements "work", the above mentioned does a lot of extra work, first you construct a new instance, then you look up if the instance itself has a slice property, as this is false the prototype chain is traversed and the slice is found on the Array.prototype and then called. Then you call it with your other array as scope, so essentially render the instance you created useless by using your other one.

Thats why Array.prototype.slice.call(myarr) is the proper way of accessing the slice method.

1 Comment

oops i didn't give -1, please state the reason who voted the down
1

Array.prototype.slice.call() seems slightly more performant, though that makes sense because it would be quicker at runtime to "look up" this method. I posit that [].slice.call() is the best choice. Here's the jsperf of reference

Let's be real, in what case would the negligible difference between the two be a major contributor to poor website performance? sounds like heaven, actually. The shorter syntax of the literal method is awesome. I'd rather save myself the half-second it'd take to type the prototype variant than be shakily more efficient.

The coffin nail of Array.prototype... some people say is that it's irresponsible because you risk altering it. But... that's stupid. Figure 1: Array.prototype = function() { console.log('foo') }; Whoopsie... That probably happens all of the time. Seriously, even granting its legitimacy is still intact, it takes me longer to type and is imo hideous compared to its sexier literal sister.

The real answer to your real question is that the functionality is exactly the same. Use whichever you will still appreciate on your deathbed.

4 Comments

thanks, @bluebill1049! I like your alias even though it has numbers, and numbers is hard.
"some people say is that it's irresponsible because you risk altering it" I wonder who those people are. I think in this case it's quite difficult to "accidentally" assign a property if all you want is call it.
exactly. perfunctory reference: stackoverflow.com/questions/9006553/…
Object.getPrototypeOf([]).slice.call() a happy compromise?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.