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?
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.
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,
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.
- ✔️: 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