简体   繁体   中英

Arguments Array in JavaScript (ES5)

Maybe that is not my evening :/ Very simple thing, I want to give an array as parameter to a function as arguments array:

function add() {
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}

The following works:

console.log(add(1,2,3,4,5,6));

But if I fill an array and give it as parameter, like:

var myNumbers = [];
for (var i=0; i<100; i++){
    myNumbers.push(i);
}
console.log(add(myNumbers));

I get trouble. I think, I miss something important about the arguments array.

How should I change the add function, so that both possibilities can work with it?

The arguments object is an array-like object, but it is not an array. It is used to represent all arguments passed into the function. You have only passed in one value into the function, so your array is actually at index 0 of the arguments object.

However, there really isn't much point using arguments here unless you need to dynamically handle things without defining an explicit API. Just declare your parameter in the add function.

function add(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}

If you want to support both cases, as per your comment, you can do something like:

function add() {
    var arr = [].concat.apply([], arguments);
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}

Explanation of [].concat.apply([], arguments)

  • []. is shorthand for Array.prototype because it's an empty array.
  • concat merges two or more arrays together, or an array and values to go into the array.
  • arguments is not an array, but many of the prototype functions will work on it, due to some array-like characteristics of the object - indexed items and the length property.
  • apply calls a function with a given context (the this binding) and any number of arguments. In this case we still want to use the array as this value to be able to call concat , followed by all the arguments we passed into add . The result is simply all arguments as a proper array.

This solution works for both situation :

function add() {
    var arr= Array.prototype.slice.call(arguments);
    arr = [].concat.apply([], arr);

    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
      sum += arr[i];
    }
    return sum;
}

Also simple solution for sum :

 function add() {
        var arr= Array.prototype.slice.call(arguments);
        arr = [].concat.apply([], arr);

        return arr.reduce(function(f, s){return f + s;}, 0);
    }

Here:

add(1,2,3,4,5,6);

...you're calling add with a series of discrete (separate) arguments, and each of them shows up in the arguments pseudo-array, 1 at arguments[0] , 2 at arguments[1] , etc.

But here:

add(myNumbers);

...you're calling add with one argument, which is an array. That's at arguments[0] .

You'll want to write add to fit how you want to call it. If you want to call it with discrete arguments, write it the way you have. If you want to write it to accept an array, have it take a single argument and loop through that (which will be the array):

function add(args) {
    //       ^------------- the one argument
    var sum = 0;
    for (var i = 0; i < args.length; i++) {
        sum += args[i];
    }
    return sum;
}

If you want to handle both , you could use Array.isArray (newish, but shimmable) to check the first argument to see if it's an array and either use it if it is or use arguments if it isn't:

function add(args) {
    if (!Array.isArray(args)) {
        args = arguments;
    }
    var sum = 0;
    for (var i = 0; i < args.length; i++) {
        sum += args[i];
    }
    return sum;
}

Side note: arguments isn't an array, it's just array-like .

您可以使用申请

add.apply(null, [1,2,3])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM