0

I know arguments is an array-like object in every function, but I'm not sure why we need it and how we use it? Below is one example that confused me...

So here why we can't simply put var args=[], instead, use slice on arguments?

(im not sure if it is a good example to explain arugments, but im also trying to understand how the apply() works here...)

_.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){
      return func.apply(null, args);
    }, wait);
  };

2 Answers 2

1

.apply() allows you to call a function while specifying two different things:

  1. The value of the this pointer inside the function call.
  2. A set of arguments to pass to the function when your source of the arguments is an array.

One will typically use .call() if the number of arguments to pass to the function is known in advance and will typically use .apply() when the number of arguments is not know in advance and thus the arguments are in an array or can be put into an array.

Presumably, slice() in the code example you show is Array.prototype.slice so that code example is grabbing the set of arguments AFTER the first two and putting them into their own array so that they can then be passed to the original function.

The arguments object in Javascript is "array-like". It has a .length property and is zero indexed like an array, but it does not have any array methods on it. So, if you want to use an array method on it like .slice() to copy some elements to a new array, you have to manually specify array methods from the Array prototype rather than directly use .slice() on the arguments object.

So, if you called:

function myFunc(a, b, c, d) {
   // four arguments present here
}

_.delay(myFunc, 100, 1, 2, 3, 4);

The inner workings of _.delay() would skip the first two arguments passed to it (because those are for use directly in _.delay() and get just the remaing last four arguments and then pass those to the callback function using .apply().

Here's a working snippet example:

var _ = {};
var slice = Array.prototype.slice;

_.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){
        func.apply(null, args);
    }, wait);
};

function myFunc() {
   log("number of arguments passed to myFunc(): " + arguments.length);
   log(JSON.stringify(slice.call(arguments)));
}

_.delay(myFunc, 500, 1, 2, 3, 4)

function log(x) {
    var div = document.createElement("div");
    div.innerHTML = x;
    document.body.appendChild(div);
}

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

Comments

1

This code will get any arguments after the first 2, and put them in a new array. If you set it to a blank array, you will not have any arguments that may have been passed in addition to the named ones.

Consider the difference between the following 2 snippets:

var slice = Array.prototype.slice;

function test(a, b) {
  var args = slice.call(arguments, 2);
  console.log(args);
}
test(1, 2, 3, 4);

Console Output:

[3, 4]

function test(a, b) {
  var args = [];
  console.log(args);
}
test(1, 2, 3, 4);

Console Output:

[]

It is necessary to call slice on the arguments array, because the arguments object is only array-like, and does not include this method.

2 Comments

but why not the additional arguments cannot be passed in if I set it to blank array?
@Danny Because there may be more arguments in the arguments object, which would be included in the sliced array. An empty array would never include them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.