Symbol.isConcatSpreadable
The
Symbol.isConcatSpreadable
well-known symbol is used to configure if an object should be flattened to its array elements when using theArray.prototype.concat()
method.
JavaScript数组的concat()方法被设计用于拼接两个数组,使用方法如下
let colors1 = ["red", "green"],
colors2 = colors1.concat(["blue", "black"]);
// 4
console.log(colors2.length);
// (4) ['red', 'green', 'blue', 'black']
console.log(colors2);
这段代码将数组colors1与一个临时数组拼接并创建新数组colors2,这个数组中包含前两个数组中的所有元素。concat方法也可以接收非数组参数,此时该方法只会将这些参数逐一添加到数组末尾
let colors1 = ["red", "green"],
colors2 = colors1.concat(["blue", "black"],"brown");
// 5
console.log(colors2.length);
// (5) ['red', 'green', 'blue', 'black', 'brown']
console.log(colors2);
这段代码中,额外传入的一个字符串作为了拼接后的第五个元素,而数组却拆分成为了两个元素。为什么数组参数就会区别对待呢?JavaScript规范声明,凡是传入了数组参数,就会自动将它们分解为独立元素。在ES6标准之前,我们无法调整这个特性。
而ES6的Symbol.isConcatSpreadable可用于增强作用于特性对象类型的concat方法的功能,有效简化其默认特性。Symbol.isConcatSpreadable属性时一个布尔值,如果该属性值为true,则表示对象有length属性和数字键,故它的数值型属性值应该被独立添加到concat调用的结果中。与其他well-known Symbol不同的是,这个Symbol属性默认情况下不会出现在标准对象中,它只是一个可选属性。
默认情况下,数组的Symbol.isConcatSpreadable属性为true,在以下代码中将这个属性修改为false。concat结果就发生了变化,数组对象不再被打平进行合并了。
const alpha = ['a', 'b', 'c'];
const numeric = [1, 2, 3];
let alphaNumeric = alpha.concat(numeric);
console.log(alphaNumeric);
// expected output: Array ["a", "b", "c", 1, 2, 3]
numeric[Symbol.isConcatSpreadable] = false;
alphaNumeric = alpha.concat(numeric);
console.log(alphaNumeric);
// expected output: Array ["a", "b", "c", Array [1, 2, 3]]
对于类数组对象,这个属性默认为false。
let collection = {
0:"Hello",
1:"world",
length:2
};
let messages = ["Hi"].concat(collection);
// 2
console.log(messages.length);
/**
* (2) ['Hi', {…}]
* 0: "Hi"
* 1: {0: 'Hello', 1: 'world', length: 2, Symbol(Symbol.isConcatSpreadable): false}
* length: 2
* [[Prototype]]: Array(0)
*/
console.log(messages);
修改Symbol.isConcatSpreadable属性为true。
let collection = {
0:"Hello",
1:"world",
length:2,
[Symbol.isConcatSpreadable]:true
};
let messages = ["Hi"].concat(collection);
// 3
console.log(messages.length);
// (3) ['Hi', 'Hello', 'world']
console.log(messages);
The @@isConcatSpreadable
symbol (Symbol.isConcatSpreadable
) can be defined as an own or inherited property and its value is a boolean. It can control behavior for arrays and array-like objects:
- For array objects, the default behavior is to spread (flatten) elements.
Symbol.isConcatSpreadable = false
can avoid flattening in these cases. - For array-like objects, the default behavior is no spreading or flattening.
Symbol.isConcatSpreadable = true
can force flattening in these cases.