JavaScript: 数组。为什么将空数组与已填充的数组连接起来会得到一个字符串?

5

我正在处理一个有关平铺数组的问题。我遇到了一些非常奇怪的事情,似乎在网上找不到答案。

为什么

[] + [1,2] = '1,2'

我似乎无法理解为什么将一个空数组添加到已存在元素的数组中会导致一个字符串,其内容为已存在元素的数组。

背后发生了什么导致这种情况出现?

以下是我的代码示例:

arr = [1, [2], [3, 4]];
arr.reduce(flatten, []); // [1, 2, 3, 4]

function flatten(a, b) {
    return a.concat(b);
}

据我所了解,reduce将'[]'设置为“初始值”,因此对于原始数组中的每个元素,它都会将其与空数组连接起来,从而“展平”该数组。

1
JavaScript不是Python,+运算符不能连接列表。数组被强制转换为字符串。尝试使用[1,2].toString(); - Jared Smith
“+”既是算术加法运算符,也是字符串连接运算符。因此,数组会自动转换为字符串以匹配运算符的参数类型。请查看Array.prototype.concat了解数组连接。 - traktor
3个回答

5
这是由于JavaScript的隐式类型转换触发了+运算符。你不能简单地对数组执行+操作,因此它们被转换为字符串(其中包含数组的逗号分隔的字符串转换值)。

5
当你在对象(数组是对象)之间使用+时,JavaScript内部调用toString()和/或valueOf()

var coercion1 = {} + {foo: 'Foo', bar: 'Bar'},
    coercion2 = [] + ['foo', 'bar'];

console.log(coercion1);
console.log(coercion2);

这与以下内容相同:

var coercion1 = "".concat({}.toString(), {foo: 'Foo', bar: 'Bar'}.toString()),
    coercion2 = "".concat([].toString(), ['foo', 'bar'].toString());

console.log(coercion1);
console.log(coercion2);

这其实就是说:

var coercion1 = "".concat({}.valueOf(), {foo: 'Foo', bar: 'Bar'}.valueOf()),
    coercion2 = "".concat([].valueOf(), ['foo', 'bar'].valueOf());

console.log(coercion1);
console.log(coercion2);

为了将一个对象转换为字符串,JavaScript 执行以下步骤:
- 如果对象有 toString() 方法,JavaScript 就会调用该方法。如果它返回原始值,JavaScript 会将该值转换为字符串(如果它还不是字符串),并返回该转换结果。[...] - 如果对象没有 toString() 方法,或该方法不返回原始值,则 JavaScript 会查找 valueOf() 方法。如果该方法存在,JavaScript 就会调用它。如果返回值是一个原始类型,JavaScript 会将该值转换为字符串(如果它还不是字符串),并返回该转换结果。 - 否则,JavaScript 无法从 toString()valueOf() 中获得原始值,于是抛出 TypeError。 David Flanagan, JavaScript权威指南

-1

使用 + 将会得到一个字符串,控制台将不包括括号。与

''+[1,2]

3
不是控制台排除了括号。 - Jared Smith
可能表达不正确,但这就是发生的事情。如果你做 {uno:11, dos:22} + "",会添加括号。从视觉上讲。 - s1mpl3
不,那会给出默认的 [object Object]。我们谈论的是数组,而不是 POJOs,它们被字符串化为逗号分隔的值。如果你想要方括号,请使用 JSON.stringify 而不是字符串强制转换。 - Jared Smith
在你的 [object Object] 上执行 .length,尽管它们只是将对象转换为字符串的可视化表示,但括号也会被计算。 - s1mpl3
再次强调,数组有自定义的 toString 实现,它们生成的字符串与对象不同。实际上,可以使用这个方法来测试一个对象是否为数组:Object.prototype.toString.call([1,2]) === '[object Array]' 但是 [1,2].toString() === '1,2' - Jared Smith

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