可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is it possible to send a variable number of arguments to a JavaScript function, from an array?
var arr = [\'a\',\'b\',\'c\']
var func = function()
{
// debug
alert(arguments.length);
//
for(arg in arguments)
alert(arg);
}
func(\'a\',\'b\',\'c\',\'d\'); // prints 4 which is what I want, then \'a\',\'b\',\'c\',\'d\'
func(arr); // prints 1, then \'Array\'
I\'ve recently written a lot of Python and it\'s a wonderful pattern to be able to accept varargs and send them. e.g.
def func(*args):
print len(args)
for i in args:
print i
func(\'a\',\'b\',\'c\',\'d\'); // prints 4 which is what I want, then \'a\',\'b\',\'c\',\'d\'
func(*arr) // prints 4 which is what I want, then \'a\',\'b\',\'c\',\'d\'
Is it possible in JavaScript to send an array to be treated as the arguments array?
回答1:
Use apply:
var arr = [\'a\',\'b\',\'c\'];
var func = function() {
alert(arguments.length);
for(var i = 0; i < arguments.length; i++) {
alert(arguments[i]);
}
};
func.apply(null, arr);
Notice that null
is used as the first argument of apply, that will set the this
keyword to the Global object (window) inside func
.
Also note that the arguments
object is not really an Array, you can convert it by :
var argsArray = Array.prototype.slice.call(arguments);
And maybe is useful to you, that you can know how many arguments a function expects:
var test = function (one, two, three) {};
test.length == 3;
But anyway you can pass an arbitrary number of arguments...
回答2:
You can actually pass as many values as you want to any javascript function. The explicitly named parameters will get the first few values, but ALL parameters will be stored in the arguments array.
To pass the arguments array in \"unpacked\" form, you can use apply, like so (c.f. Functional Javascript):
var otherFunc = function() {
alert(arguments.length); // Outputs: 10
}
var myFunc = function() {
alert(arguments.length); // Outputs: 10
otherFunc.apply(this, arguments);
}
myFunc(1,2,3,4,5,6,7,8,9,10);
回答3:
The splat and spread operators are part of ES6, the planned next version of Javascript. So far only Firefox supports them. This code works in FF16+:
var arr = [\'quick\', \'brown\', \'lazy\'];
var sprintf = function(str, ...args)
{
for (arg of args) {
str = str.replace(/%s/, arg);
}
return str;
}
sprintf.apply(null, [\'The %s %s fox jumps over the %s dog.\', ...arr]);
sprintf(\'The %s %s fox jumps over the %s dog.\', \'slow\', \'red\', \'sleeping\');
Note the awkard syntax for spread. The usual syntax of sprintf(\'The %s %s fox jumps over the %s dog.\', ...arr);
is not yet supported. You can find an ES6 compatibility table here.
Note also the use of for...of
, another ES6 addition. Using for...in
for arrays is a bad idea.
回答4:
There are two methods as of ES2015.
The arguments
Object
This object is built into functions, and it refers to, appropriately, the arguments of a function. It is not technically an array, though, so typical array operations won\'t work on it. The suggested method is to use Array.from
or the spread operator to create an array from it.
I\'ve seen other answers mention using slice
. Don\'t do that. It prevents optimizations (source: MDN).
Array.from(arguments)
[...arguments]
However, I would argue that arguments
is problematic because it hides what a function accepts as input. An arguments
function typically is written like this:
function mean(){
let args = [...arguments];
return args.reduce((a,b)=>a+b) / args.length;
}
Sometimes, the function header is written like the following to document the arguments in a C-like fashion:
function mean(/* ... */){ ... }
But that is rare.
As for why it is problematic, take C, for example. C is backwards compatible with an ancient pre-ANSI dialect of the language known as K&R C. K&R C allows function prototypes to have an empty arguments list.
int myFunction();
/* This function accepts unspecified parameters */
ANSI C provides a facility for varargs
(...
), and void
to specify an empty arguments-list.
int myFunction(void);
/* This function accepts no parameters */
Many people inadvertently declare functions with an unspecified
arguments list (int myfunction();
), when they expect the function to take zero arguments. This is technically a bug because the function will accept arguments. Any number of them.
A proper varargs
function in C takes the form:
int myFunction(int nargs, ...);
And JavaScript actually does have something similar to this.
Spread Operator / Rest Parameters
I\'ve already shown you the spread operator, actually.
...name
It\'s pretty versatile, and can also be used in a function\'s argument-list (\"rest parameters\") to specify varargs in a nicely documented fashion:
function mean(...args){
return args.reduce((a,b)=>a+b) / args.length;
}
Or as a lambda expression:
((...args)=>args.reduce((a,b)=>a+b) / args.length)(1,2,3,4,5); // 3
I much prefer the spread operator. It is clean and self-documenting.
回答5:
The apply
function takes two arguments; the object this
will be binded to, and the arguments, represented with an array.
some_func = function (a, b) { return b }
some_func.apply(obj, [\"arguments\", \"are\", \"here\"])
// \"are\"
回答6:
It\'s called the splat
operator. You can do it in JavaScript using apply
:
var arr = [\'a\',\'b\',\'c\',\'d\'];
var func = function() {
// debug
console.log(arguments.length);
console.log(arguments);
}
func(\'a\',\'b\',\'c\',\'d\'); // prints 4 which is what I want, then \'a\',\'b\',\'c\',\'d\'
func(arr); // prints 1, then \'Array\'
func.apply(null, arr);
回答7:
This is a sample program for calculating sum of integers for variable arguments and array on integers. Hope this helps.
var CalculateSum = function(){
calculateSumService.apply( null, arguments );
}
var calculateSumService = function(){
var sum = 0;
if( arguments.length === 1){
var args = arguments[0];
for(var i = 0;i<args.length; i++){
sum += args[i];
}
}else{
for(var i = 0;i<arguments.length; i++){
sum += arguments[i];
}
}
alert(sum);
}
//Sample method call
// CalculateSum(10,20,30);
// CalculateSum([10,20,30,40,50]);
// CalculateSum(10,20);
回答8:
(function(window) {
var proxied = window.alert;
window.alert = function() {
return proxied.apply(window, arguments);
};
}(this));
alert(13, 37);
回答9:
With ES6 you can use rest parameters for varagrs
. This takes the argument list and converts it to an array.
function logArgs(...args) {
console.log(args.length)
for(let arg of args) {
console.log(arg)
}
}
回答10:
For those who were redirected here from Passing variable number of arguments from one function to another (which should not be marked as a duplicate of this question):
If you\'re trying to pass a variable number of arguments from one function to another, since JavaScript 1.8.5 you can simply call apply()
on the second function and pass in the arguments
parameter:
var caller = function()
{
callee.apply( null, arguments );
}
var callee = function()
{
alert( arguments.length );
}
caller( \"Hello\", \"World!\", 88 ); // Shows \"3\".
Note: The first argument is the this
parameter to use. Passing null
will call the function from the global context, i.e. as a global function instead of the method of some object.
According to this document, the ECMAScript 5 specification redefined the apply()
method to take any \"generic array-like object\", instead of strictly an Array. Thus, you can directly pass the arguments
list into the second function.
Tested in Chrome 28.0, Safari 6.0.5, and IE 10. Try it out with this JSFiddle.
回答11:
Yes you can pass variable no. of arguments to a function. You can use apply
to achieve this.
E.g.:
var arr = [\"Hi\",\"How\",\"are\",\"you\"];
function applyTest(){
var arg = arguments.length;
console.log(arg);
}
applyTest.apply(null,arr);