Jonah
Jonah

Reputation: 16232

Confused About Resig Curry Example And "arguments" Object

In this article, John Resig discusses this snippet for currying:

Function.prototype.curry = function() {
    var fn = this, args = Array.prototype.slice.call(arguments);
    return function() {
      return fn.apply(this, args.concat(
        Array.prototype.slice.call(arguments)));
    };
  };

I am confused about the expression Array.prototype.slice.call(arguments).

  1. Here "arguments" is the "this" argument to Array's slice() method, but "slice()" requires an argument itself, so I would think you'd need to do something like Array.prototype.slice.call(arguments, <someIndex>). I don't understand how that code can be working as is.

  2. According to the docs on "arguments", "arguments" is not actually an Array, but only an array like object. How are we calling "slice()" on it? And if I put in the code console.log(arguments.slice()) I get an error saying that the object does not have a slice method.

What's going on here?

Upvotes: 1

Views: 79

Answers (2)

bfavaretto
bfavaretto

Reputation: 71939

Answer to first question:

If you call slice on an array without arguments, it will just return a copy of the array. Array.prototype.slice.call(arguments) does just the same, but operates on the arguments object, returning an array.

Answer to second question:

We can call slice on arguments because it's a "generic" method (see the note here). When you pass the arguments object as this, slice will treat it as an array. Since arguments is an array-like object that contains a length property, it just works.

Upvotes: 4

Pointy
Pointy

Reputation: 413826

The argument to .slice() is optional. If it's absent, the function just returns a copy of the original array (or array-like object).

The .slice() function just cares about the presence of a "length" property on the this object. Thus, because "arguments" does have a "length" property, .slice() is happy.

Upvotes: 3

Related Questions