为什么.join()不能使用函数参数?

为什么这个工作(返回“一,二,三”):

var words = ['one', 'two', 'three']; $("#main").append('<p>' + words.join(", ") + '</p>'); 

和这个工作(返回“列表:111”):

 var displayIt = function() { return 'the list: ' + arguments[0]; } $("#main").append('<p>' + displayIt('111', '222', '333') + '</p>'); 

但不是这样(返回空白):

 var displayIt = function() { return 'the list: ' + arguments.join(","); } $("#main").append('<p>' + displayIt('111', '222', '333') + '</p>'); 

我有什么要做我的“参数”variables是使用.join()呢?

它不起作用,因为arguments对象不是数组,虽然它看起来像。 它没有join方法:

 >>> var d = function() { return '[' + arguments.join(",") + ']'; } >>> d("a", "b", "c") TypeError: arguments.join is not a function 

要将arguments转换为数组,可以这样做:

 var args = Array.prototype.slice.call(arguments); 

现在join将工作:

 >>> var d = function() { var args = Array.prototype.slice.call(arguments); return '[' + args.join(",") + ']'; } >>> d("a", "b", "c"); "[a,b,c]" 

或者,你可以使用jQuery的makeArray ,它将尝试将“几乎数组”的arguments变成数组:

 var args = $.makeArray(arguments); 

下面是Mozilla的参考资料 (我最喜欢的资源)就是这样说的:

arguments对象不是一个数组。 它与数组类似,但除length外没有任何数组属性。 例如,它没有pop方法。 …

arguments对象只能在函数体中使用。 尝试访问函数声明外的参数对象会导致错误。

如果您对其他Array.prototype方法不感兴趣,并且只想使用join ,则可以直接调用它,而不必将其转换为数组:

 var displayIt = function() { return 'the list: ' + Array.prototype.join.call(arguments, ','); }; 

另外,如果你没有定义一个分隔符,你可能会发现这个逗号是默认的分隔符,按照规格 ,逗号将被使用。

只需使用jQuery实用程序函数makeArray

arguments不是一个数组,它是一个对象。 但是,既然它是“数组”的,你可以调用jQuery实用函数makeArray使其工作:

 var displayIt = function() { return 'the list: ' + $.makeArray(arguments).join(","); } $("#main").append('<p>' + displayIt('111', '222', '333') + '</p>'); 

哪个会输出:

 <p>the list: 111,222,333</p> 

你可以使用这个jQuery .joinObj扩展/我所做的插件 。

正如你将在小提琴中看到的那样,你可以使用它如下:

 $.joinObj(args, ","); 

要么

 $.(args).joinObj(","); 

插件代码:

 (function(c){c.joinObj||(c.extend({joinObj:function(a,d){var b="";if("string"===typeof d)for(x in a)switch(typeof a[x]){case "function":break;case "object":var e=c.joinObj(a[x],d);e!=__proto__&&(b+=""!=b?d+e:e);break;default:"selector"!=x&&"context"!=x&&"length"!=x&&"jquery"!=x&&(b+=""!=b?d+a[x]:a[x])}return b}}),c.fn.extend({joinObj:function(a){return"object"===typeof this&&"string"===typeof a?c.joinObj(this,a):c(this)}}))})(jQuery); 

你可以使用typeof来看看这里发生了什么:

 >>> typeof(['one', 'two', 'three']) "object" >>> typeof(['one', 'two', 'three'].join) "function" >>> typeof(arguments) "object" >>> typeof(arguments.join) "undefined" 

在这里你可以看到typeof在两种情况下都返回“object”,但是只有一个对象定义了连接函数。

arguments不是一个jQuery对象,只是一个普通的JavaScript对象。 在尝试调用.join()之前将其扩展。 我想你会写:

 return 'the list:' + $(arguments)[0]; 

(我不太熟悉jQuery,只有Prototype,所以我希望这不是完全假的。)

编辑:这是错的! 但是在他的回应中,Doug Neiner描述了我想要完成的事情。

我不知道是否有一个简单的方法来将参数转换成数组,但你可以试试这个:

 var toreturn = "the list:"; for(i = 0; i < arguments.length; i++) { if(i != 0) { toreturn += ", "; } toreturn += arguments[i]; } 

目前你不能join数组参数,因为它们不是数组, 如下所示

所以你必须先把它们变成像这样的数组,

 function f() { var args = Array.prototype.slice.call(arguments, f.length); return 'the list: ' + args.join(','); } 

或者像这样,缩短一点

 function displayIt() { return 'the list: ' + [].join.call(arguments, ','); } 

如果您正在使用类似babel或兼容的浏览器来使用es6function,您也可以使用rest参数来执行此操作。

 function displayIt(...args) { return 'the list: ' + args.join(','); } displayIt('111', '222', '333'); 

这会让你做更酷的东西

 function displayIt(start, glue, ...args) { return start + args.join(glue); } displayIt('the start: ', '111', '222', '333', ',');