为什么我不能在函数的参数上调用数组方法?

24

我有一个函数可以接受任意数量的参数...

const getSearchFields = () => {        
    const joined = arguments.join('/'); 
};
我想要一个字符串,其中包含函数传递的所有参数,这些参数用/字符连接。我一直得到这个错误:

args.join不是一个函数

请问有人能告诉我我做错了什么吗?


为什么要编辑它以使用ES6语法? - Tim Down
@TimDown 当我更新它时感觉很正确。我猜如果你在暗示这样做有有效的反对理由,那么可能是有道理的。 - alex
我不太确定,但似乎有点奇怪,因为2009年的答案是用ES3编写的。我现在上这里的时间不够多,不知道将旧问题修改为现代语法是被认为是好还是坏。 - Tim Down
据我所知,鼓励始终保持答案的最新状态,即使问题已经过时。在这种情况下,现在问题看起来不那么过时了。 - alex
1
@alex,我也更新了我的回答,提供了一种ES6的方法来实现它。谢谢。 - Christian C. Salvadó
@CMS 哇,你回来了 :) - alex
8个回答

48

arguments是伪数组,而不是真正的数组。可以使用join方法来处理真正的数组。

你需要有所突破:

var convertedArray = [];

for(var i = 0; i < arguments.length; ++i)
{
 convertedArray.push(arguments[i]);
}

var argsString = convertedArray.join('/');

与其他帖子类似,您可以使用以下方法作为简写:

var argsString = Array.prototype.join.call(arguments, "/");

6
将参数对象转换为数组,你可以简单地这样做:var convertedArray = Array.prototype.slice.call(arguments); - Christian C. Salvadó
你也可以通过使用splice来简化循环... var args = [].splice.call(arguments,0); - Russ Bradberry
3
@Russ:更简短,但在IE上不起作用,你应该直接调用Array.prototype.slice函数。 - Christian C. Salvadó

14

如上所述,arguments对象并不是真正的数组,但是您可以通过访问Array.prototype,并使用applycall来执行它们以更改上下文,直接应用数组函数:

var argsString = Array.prototype.join.call(arguments, '/');
编辑: 由于原问题在近9年后更新了使用ES6语法,现在该语言提供了本地结构来处理这种情况,因此我感到有必要提供一个ES6答案。

ES6标准引入了扩展运算符,您可以轻松地将参数作为数组对象接收,例如:

function sum(...numbers) {
  return numbers.reduce((sum, value) => sum + value);
}

console.log(sum(1,2,3,4)); // 10

应用于您的示例:
const getSearchFields = (...fields) => {        
  const joined = fields.join('/'); 
};

您也可以使用展开运算符进行函数调用。假设您有一个数组,并且想要调用一个函数,将数组的每个元素作为函数调用的参数传递,现在您可以简单地执行以下操作:

function sum(a, b, c, d) {
  return a + b + c + d;
}

var array = [1, 2, 3, 4];
console.log(sum(...array)); // 10

同时,您可以期望一些参数,并将其余参数作为最后一个定义的参数传递:

function processList(first, ...rest) {
  // ...
}

而使用展开运算符的用途还不止于此,例如对象复制、在数组中展开数组等,超出了这个问题的范围...


'/' 需要用括号括起来 - David Andres
4
不,我使用的是call而不是apply。 - Christian C. Salvadó
2
更正一下,当调用apply时可能需要这样做。你正在使用call。我的错误。 - David Andres

8
如果您正在使用 jQuery 1.2+,可以使用$.makeArray()

将类数组对象转换为真正的JavaScript数组。

从问题中的示例中,只需使用此行代码:

var args = $.makeArray(arguments);

仅供记录,这在jQuery 1.11.0中对我有效。 - Celt

5

参数并不是真正的数组。

试试这个:

var args = [].splice.call(arguments,0);
var argsString = args.join('/');

2
问题在于arguments是一个类数组对象(它具有映射到传递参数的编号属性和一个length属性),但实际上它并不是一个数组。

在旧时代,你可以使用Array.prototype.slice.call(arguments)(以及其他方法)将其转换为真正的数组。

然而,现在我们运气更好一些(当然这取决于您所支持的平台)。你可以选择...

const getSearchFields = (...args) => {
   Array.isArray(args); // true
};

...or...

const getSearchFields = () => {
   const args = Array.from(arguments);
   Array.isArray(args); // true
};

第一个例子更好,因为...
  • 你可以在函数体中省略额外的步骤获得正常的数组创建。
  • arguments是一个神奇的变量(它没有被明确地定义,那么它从哪里来呢?)
  • 在非严格模式下,它对命名参数有一些有趣的行为(请注意,您应该始终使用'use strict')。
  • 第一个示例具有更清晰的意图(显式创建包含所有参数的数组)。

0

arguments 不是 JavaScript 数组;它是一个特殊的对象,没有 join 方法。


-1

-2
你必须给变量赋值才能使其正常工作。
var a = ['Wind', 'Rain', 'Fire'];

var myVar1 = a.join();

var myVar2 = a.join(', ');

var myVar3 = a.join(' + ');

var myVar4 = a.join('');

1
你的陈述是不正确的,也没有回答问题。 - alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接