Search code examples
javascriptfunctionecmascript-5ecmascript-3

Should arguments.slice() work in ES5?


I'm watching Crockford on Javascript - Act III: Function the Ultimate at around 41 mins 26 seconds. The code on his screen uses arguments.slice() in a way that causes an error for me.

function curry(func){
    var args = arguments.slice(1);
    ...
}

He explains it like this:

I'll first get an array of arguments, except the first one, because the first one is a function and I don't need that one. In this case I'm assuming I'm on ES5, so I'm not doing the awful Array.prototype.apply() trick.

The problem is that running arguments.slice() results in this error:

Uncaught TypeError: arguments.slice is not a function

I'm testing on modern browsers that definitely have ES5! The only way I can get the code to work is if I use some "awful" tricks, (as he calls them) e.g. Array.prototype.slice.apply(arguments, [1]) or [].slice.call(arguments, 1);.

Is he just mistaken? Does his slide have a typo in it? Why doesn't arguments.slice() work in my ES5 browsers?


Solution

  • Quoting TC39 member Allen Wirfs-Brock:

    Until very late in the development of ECMAScript 5, argument object were going to inherit all of the Array.prototype methods. But the "final draft" of ES5 approved by TC39 in Sept. 2009 did not have this feature.

    Making the arguments object inherit from the Array prototype was actually planned, but when put in practice it broke the web. Hence it was removed from the final revision before official publication.


    Nowadays, with ECMAScript 2015 (a.k.a. ES6) standardized, the best approach is to use rest parameters:

    function curry(func, ...args) {
      // ...
    }
    

    Which is equivalent to ES5:

    function curry(func) {
      var args = [].slice.call(arguments, 1);
      // ...
    }
    

    This feature is already natively available in Firefox and Edge, and available everywhere if you use a JavaScript compiler such as Babel.