es6数组之扩展运算符操作实例分析


Posted in Javascript onApril 25, 2020

本文实例讲述了es6数组之扩展运算符操作。分享给大家供大家参考,具体如下:

扩展运算符(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')]

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

function push(array, ...items) {
 array.push(...items)
}
function add(x, y) {
 return x + y
}

const numbers = [4, 38]
add(...numbers) // 42

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

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

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

扩展运算符后面还可以放置表达式。

const arr = [
 ...(x > 0 ? ['a'] : []),
 'b'
]

如果扩展运算符后面是一个空数组,则不产生任何效果。

[...[], 1]

注意,扩展运算符如果放在括号中,javaScript引擎就会认为这是函数调用。如果这时不是函数调用,就会报错。

(...[1, 2])
// Uncaught SyntaxError: Unexpected number

console.log((...[1, 2]))
// Uncaught SyntaxError: Unexpected number

console.log(...[1, 2])
// 1 2

上面前两种情况都会报错,因为扩展运算符所在的括号不是函数调用,而第三种情况console.log(…[1, 2])就不会报错,因为这时是函数调用。

下面是扩展运算符取代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的写法
let arr1 = [0, 1, 2]
let arr2 = [3, 4, 5]
arr1.push(...arr2)

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

下面是另外一个例子。

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

扩展运算符的应用

1)复制数组

数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。

const a1 = [1, 2]
const a2 = a1 
a2[0] = 2
a1 // [2, 2]

上面代码中,a2并不是a1的克隆,而是指向同一份数据的另一个指针,修改a2,会直接导致a1的变化。

ES5只能用变通方法来复制数组。

const a1 = [1, 2]
const a2 = a1.concat()

a2[0] = 2 
a1 //[1, 2]

ES6写法

const a1 = [1, 2]
// 写法1
const a2 = [...a1]
// 写法2
const [...a2] = a1

2)合并数组

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

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

不过,这两种方法都是浅拷贝,使用的时候需要注意。

const a1 = [{foo: 1}]
const a2 = [{bar: 2}]
const a3 = a1.concat(a2)
const a4 = [...a1, ...a2]

a3[0] === a1[0] // true
a4[0] === a1[0] // true

上面代码中,a3和a4是用两种不同方法合并而成的新数组,但是它们的成员都是对原数组成员的引用,这就是浅拷贝,如果修改了原数组的成员,会同步反映到新数组。

3)与解构赋值结合

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

// 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 [...butLast, last] = [1, 2, 3, 4, 5];
// 报错

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

(4)字符串

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

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

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

let arrayLike = {
 '0': 'a',
 '1': 'b',
 length:2
}

// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];

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

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

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

let arr = [...map.keys()]; // [1, 2, 3]

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
取得一定长度的内容,处理中文
Dec 20 Javascript
javascript对象的property和prototype是这样一种关系
Mar 24 Javascript
跟我学习javascript解决异步编程异常方案
Nov 23 Javascript
JS组件Bootstrap Select2使用方法详解
Apr 17 Javascript
简单谈谈Vue 模板各类数据绑定
Sep 25 Javascript
AngularJS实现的输入框字数限制提醒功能示例
Oct 26 Javascript
Angular2的管道Pipe的使用方法
Nov 07 Javascript
详解如何使用webpack在vue项目中写jsx语法
Nov 08 Javascript
layui表格checkbox选择全选样式及功能的实例
Mar 07 Javascript
Vue.js 中的 v-cloak 指令及使用详解
Nov 19 Javascript
JS+CSS+HTML实现“代码雨”类似黑客帝国文字下落效果
Mar 17 Javascript
vue抽出组件并传值实例
Jul 31 Javascript
es6函数之尾调用优化实例分析
Apr 25 #Javascript
es6函数之尾递归用法实例分析
Apr 25 #Javascript
javascript 易错知识点实例小结
Apr 25 #Javascript
javascript执行上下文、变量对象实例分析
Apr 25 #Javascript
JavaScript ECMA-262-3 深入解析(二):变量对象实例详解
Apr 25 #Javascript
JavaScript ECMA-262-3 深入解析(一):执行上下文实例分析
Apr 25 #Javascript
使用 Jest 和 Supertest 进行接口端点测试实例详解
Apr 25 #Javascript
You might like
php 常用字符串函数总结
2008/03/15 PHP
php 调试利器debug_print_backtrace()
2012/07/23 PHP
php合并js请求的例子
2013/11/01 PHP
php制作文本式留言板
2015/03/18 PHP
PHP YII框架开发小技巧之模型(models)中rules自定义验证规则
2015/11/16 PHP
File文件控件,选中文件(图片,flash,视频)即立即预览显示
2009/04/09 Javascript
使用jQuery解决IE与FireFox下createElement方法的差异
2013/11/14 Javascript
jQuery中验证表单提交方式及序列化表单内容的实现
2014/01/06 Javascript
Extjs grid panel自带滚动条失效的解决方法
2014/09/11 Javascript
javascript 继承学习心得总结
2016/03/17 Javascript
同步文本框内容JS代码实现
2016/08/04 Javascript
js获取当前时间(昨天、今天、明天)
2016/11/23 Javascript
浅谈JS验证表单文本域输入空格的问题
2017/02/14 Javascript
jQuery+CSS实现的table表格行列转置功能示例
2018/01/08 jQuery
JS实现显示当前日期的实例代码
2018/07/03 Javascript
微信小程序实现之手势锁功能实例代码
2018/07/19 Javascript
详解一个基于react+webpack的多页面应用配置
2019/01/21 Javascript
Vue2.x通用编辑组件的封装及应用详解
2019/05/28 Javascript
[01:53]2016完美“圣”典风云人物:Maybe专访
2016/12/05 DOTA
Python 类与元类的深度挖掘 I【经验】
2016/05/06 Python
获取python文件扩展名和文件名方法
2018/02/02 Python
windows环境下tensorflow安装过程详解
2018/03/30 Python
pandas获取groupby分组里最大值所在的行方法
2018/04/20 Python
Pyqt5如何让QMessageBox按钮显示中文示例代码
2019/04/11 Python
Python实现字典按key或者value进行排序操作示例【sorted】
2019/05/03 Python
python 计算方位角实例(根据两点的坐标计算)
2020/01/17 Python
浅谈Python中文件夹和python package包的区别
2020/06/01 Python
Opencv图像处理:如何判断图片里某个颜色值占的比例
2020/06/03 Python
西班牙网上书店:Casa del Libro
2016/11/01 全球购物
阿迪达斯荷兰官方网站:adidas荷兰
2018/03/16 全球购物
香港万宁官方海外旗舰店:香港健与美连锁店
2018/09/27 全球购物
党务公开方案
2014/05/06 职场文书
党的群众路线教育实践活动对照检查材料(教师)
2014/09/24 职场文书
只用40行Python代码就能写出pdf转word小工具
2021/05/31 Python
MYSQL 的10大经典优化案例场景实战
2021/09/14 MySQL
Win10加载疑难解答时出错发生意外错误的解决方法
2022/07/07 数码科技