1  含义

扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

该运算符主要用于函数调用。

function push(array, ...items) {
array.push(...items);
}
function add(x, y) {
return x + y;
}
var numbers = [4, 38];
add(...numbers) // 42

上面代码中,array.push(...items)和add(...numbers)这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。

扩展运算符与正常的函数参数可以结合使用,非常灵活。

function f(v, w, x, y, z) { }
var args = [0, 1];
f(-1, ...args, 2, ...[3]);

2  替代数组的 apply 方法

由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了。

// ES5 的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f.apply(null, args);
// ES6 的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f(...args);

下面是扩展运算符取代apply方法的一个实际的例子,应用Math.max方法,简化求出一个数组最大元素的写法。

// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
//  等同于
Math.max(14, 3, 77);

上面代码表示,由于 JavaScript 不提供求数组最大元素的函数,所以只能套用Math.max函数,将数组转为一个参数序列,然后求最大值。有了扩展运算符以后,就可以直接用Math.max了。

另一个例子是通过push函数,将一个数组添加到另一个数组的尾部。

// ES5 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);
// ES6 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);

上面代码的 ES5 写法中,push方法的参数不能是数组,所以只好通过apply方法变通使用push方法。有了扩展运算符,就可以直接将数组传入push方法。
下面是另外一个例子。

// ES5
new (Date.bind.apply(Date, [null, 2015, 1, 1]))
// ES6
new Date(...[2015, 1, 1]);

3  扩展运算符的应用

( 1 )合并数组

扩展运算符提供了数组合并的新写法。

// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

( 2 )与解构赋值结合

扩展运算符可以与解构赋值结合起来,用于生成数组。

// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
下面是另外一些例子。
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []:
const [first, ...rest] = ["foo"];
first // "foo"
rest // []

如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

const [...butLast, last] = [1, 2, 3, 4, 5];
//  报错
const [first, ...middle, last] = [1, 2, 3, 4, 5];
//  报错

( 3 )函数的返回值

JavaScript 的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。

var dateFields = readDateFields(database);
var d = new Date(...dateFields);

上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数Date。

( 4 )字符串

扩展运算符还可以将字符串转为真正的数组。

[...'hello']
// [ "h", "e", "l", "l", "o" ]

上面的写法,有一个重要的好处,那就是能够正确识别 32 位的 Unicode 字符。

'x\uD83D\uDE80y'.length // 4
[...'x\uD83D\uDE80y'].length // 3

上面代码的第一种写法, JavaScript 会将 32 位 Unicode 字符,识别为 2 个字符,采用扩展运算符就没有这个问题。因此,正确返回字符串长度的函数,可以像下面这样写。

function length(str) {
return [...str].length;
}
length('x\uD83D\uDE80y') // 3

凡是涉及到操作 32 位 Unicode 字符的函数,都有这个问题。因此,最好都用扩展运算符改写。

let str = 'x\uD83D\uDE80y';
str.split('').reverse().join('')
// 'y\uDE80\uD83Dx'
[...str].reverse().join('')
// 'y\uD83D\uDE80x'

上面代码中,如果不用扩展运算符,字符串的reverse操作就不正确。

( 5 )实现了 Iterator 接口的对象

任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组。

var nodeList = document.querySelectorAll('div');
var array = [...nodeList];

上面代码中,querySelectorAll方法返回的是一个nodeList对象。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于NodeList对象实现了 Iterator 接口。

对于那些没有部署 Iterator 接口的类似数组的对象,扩展运算符就无法将其转为真正的数组。

let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];

上面代码中,arrayLike是一个类似数组的对象,但是没有部署 Iterator 接口,扩展运算符就会报错。这时,可以改为使用Array.from方法将arrayLike转为真正的数组。

( 6 ) Map 和 Set 结构, Generator 函数

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构。

let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]

Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。

var go = function*(){
yield 1;
yield 2;
yield 3;
};
[...go()] // [1, 2, 3]

上面代码中,变量go是一个 Generator 函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。
如果对没有iterator接口的对象,使用扩展运算符,将会报错。

var obj = {a: 1, b: 2};
let arr = [...obj]; // TypeError: Cannot spread non-iterable object

es6 扩展运算符 三个点(...)相关推荐

  1. ES6——扩展运算符/三点运算符(...)

    扩展运算符(spread)是三个点(...). 数组的扩展运算符 对于数组来说,它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. console.log(...[1, 2, 3]) ...

  2. JS之ES6扩展运算符三个点(...)用于剥离{} 获取属性值

    1.用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中 let bar = { a: 1, b: 2 }; let baz = { ...bar }; // { a: 1, b: 2 } 等价于 ...

  3. ES6 扩展运算符 三个点(...)

    参考文档 点击打开链接 1. 用于函数调用 2. 数组拼接,代替concat方法 3. 计算最大值 4. 结合结构赋值使用 (只能放在最后一位,否则会报错) 5. 函数只能返回一个值,可用... 变通 ...

  4. ES6扩展运算符(三点符号), 解构

    http://www.cnblogs.com/chrischjh/p/4848934.html 转载于:https://www.cnblogs.com/lianxisheng/p/10421967.h ...

  5. ES6扩展运算符的几个小技巧

    es6扩展运算符,也就是...  ,作用是将一个数组转为用逗号分隔的参数序列. 那么问题来了,我们为啥要用这么奇怪的东东涅,当然因为它能大大提高我们的开发效率.所以,可别小看这三个点. 1.复制数组( ...

  6. ES6 - 扩展运算符与Object.assign对象拷贝与合并

    文章目录 扩展运算符能做什么? 什么是深浅拷贝 使用ES6扩展运算符 对象浅拷贝 对象合并 Object.assign Object.assign详解 Object.assign()实用 给对象添加属 ...

  7. ES6增加了扩展运算符: ... 三个点是ES几的

    ES6 的扩展运算符( spread )是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. 1.将一个数组转为用逗号分隔的参数序列(把数组中元素展开). 如下: ...

  8. javascript ES6 新特性之 扩展运算符 三个点 ...

    对于 ES6 新特性中的 ... 可以简单的理解为下面一句话就可以了: 对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中. 作用类似于 Object.assign() ...

  9. php es6写法,ES6...扩展运算符(示例代码)

    在数组中的应用 扩展运算符(spread)是三个点(...).它好比 rest 参数的逆运算,++将一个数组转为用逗号分隔的参数序列++. console.log(...[1, 2, 3]) // 1 ...

  10. ES6——扩展运算符的作用以及使用场景

    文章目录 对象扩展运算符 解构赋值 扩展运算符 数组扩展运算符 替代函数的apply() 方法 扩展运算符的应用 复制数组 合并数组 与解构赋值结合 字符串 实现了Iterator接口的对象 对象扩展 ...

最新文章

  1. 【物理方程】物理学中最难的方程之一,你知道多少?
  2. 对Spring IOC的理解(转)
  3. 作为Java程序员,这些开源工具你应该要学习!
  4. Layui layer详细参数解释说明
  5. XML入门经典(第4版)pdf
  6. 查看Wordpress数据表关系
  7. java打印jsp_在java中实现对FORM的打印功能
  8. asp.net大型制造业进销存源码 c#源代码 bs 本系统 为ASP.NET C# WinForm源码,数据库为SQL Server。系统完全开源,
  9. 编程随想 关系图_邹军:玩转数控编程,这里有个大招分享给你
  10. python就业班-淘宝-目录.txt
  11. BiDi单纤双向光模块全解析
  12. halcon脚本-找直线并拟合
  13. Camera Self-Calibration: Theory and Experiments
  14. Android TextView详解(一)
  15. 论文查重率多少算正常?
  16. [iOS]图表(UUChartView)
  17. 电脑使用年限怎么查询
  18. 路由器WAN口和LAN口的IP地址的区别
  19. 你知道GPU对Ansys Fluent仿真有多重要吗?
  20. PB 金额小写转换成大写

热门文章

  1. linux路由表命令,在linux下永久保存路由表的写法(转)
  2. iphone与计算机连接,苹果usb怎么与电脑连接_苹果怎么设置与电脑连接的图文步骤...
  3. 433m的模块含义及该如何适当的选择对应的无线模块
  4. Affinity Propagation
  5. VHDL n进制计数器
  6. 启动计算机键盘没反应,电脑键盘个别键没反应怎么办
  7. 音视频5.1——MediaCodec 同步方式完成AAC硬解成PCM
  8. Hive解决return code 3问题
  9. 河北省计算机专业对口大学分数线,计算机对口升学河北分数线2017
  10. 2019各种比赛总结