JavaScript 扩展运算符

扩展运算符是 ES6 语法,推出距今已有数年,但似乎并不常见。它有几种用例能让 JavaScript 代码更加有效使用,本文将作一个梳理。

不使用 apply 方法呼叫函数

这里指的是 Function.prototype.apply,它允许我们将实参以数组形式传入函数并依次对应到形参上。

1
2
3
4
function doStuff (x, y, z) {}
var args = [0, 1, 2];
// Call the function, passing args
doStuff.apply(null, args);

通过扩展运算符我们可以避免使用 apply 并且轻松地使用它呼叫函数。

1
doStuff(...args);

代码更少,更干净,而且不需要使用多余的 null

作用于数组

扩展运算符可以用来代替 concatslice 这些数组函数。

1
2
3
4
5
6
// joining arrays
const odd = [1, 3, 5];
const nums = [2, 4, 6].concat(odd);
// cloning arrays
const arr = [1, 2, 3, 4];
const arr2 = arr.slice()

简写:

1
2
3
4
5
6
7
// joining arrays
const odd = [1, 3, 5];
const nums = [2, 4, 6, ...odd];
console.log(nums); // [ 2, 4, 6, 1, 3, 5 ]
// cloning arrays
const arr = [1, 2, 3, 4];
const arr2 = [...arr];

不像 concat 函数,可以使用扩展运算符来在一个数组中任意处插入另一个数组。

1
2
const odd = [1, 3, 5];
const nums = [2, ...odd, 4, 6];

展开 HTMLCollection

此外,扩展运算符在前端还有一个应用场景。通过 Element.children 选择的元素,返回的是一个 HTMLCollection 对象而非 Array。这意味着你不能直接调用 forEach 方法来遍历它,而是需要一些额外的代码。比较简单的有这样几种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var targets = document.body.children;

[].forEach.call(targets, function(target) {
target.style.color = "red";
});

for (var i = 0; i < targets.length; ++i) {
targets[i].style.color = "green";
}

for (var target of targets) {
target.style.color = "blue";
}

Array.from(targets).forEach(function(target) {
target.style.color = "orange";
});

而直接使用扩展运算符展开 HTMLCollection 是这样的:

1
2
3
[...document.body.children].forEach(function(target) {
target.style.color = "black";
});

同理,document.querySelectorAll 返回的 NodeList 对象有 forEach 方法,但是却没有 map 方法。使用拓展运算符可以优美地解决这个问题。

1
2
3
[...document.querySelectorAll("p")].map(function(target) {
return target.innerText;
});

在 Hexo 的 NexT 主题中,就多次使用了这一技巧。

解构对象

也可以使用扩展运算符解构:

1
2
3
4
const { a, b, ...z } = { a: 1, b: 2, c: 3, d: 4 };
console.log(a) // 1
console.log(b) // 2
console.log(z) // { c: 3, d: 4 }

拆分字符串

一个典型的例子是:

1
2
const str = "hello";
[...str]; // => ['h', 'e',' l',' l', 'o']

就连 Emoji 也能扩展

很多 Emoji 字符不是独立的 Unicode 字符,而是由多个 Emoji 组合而成。最常见的就是家庭 Emoji 和有肤色的 Emoji,例如👪和👨‍👩‍👧‍👧。这点在前面的文章 Unicode 字符与颜文字表情中也有提到。
神奇的事情是,如果使用扩展运算符的话,它们是可以拆散的!

这些复合 Emoji 字符甚至还允许做替换,形成新的 Emoji 字符。

不得不说这是一种绝妙的使用方式。


拓展阅读:[译] 6 种 JavaScript 展开操作符的绝妙使用