ES6+ 展开语法
1. 前言
ES6 新增了 ... 的语法糖,主要用于展开语法和剩余语法中,本节先来说说展开语法。展开语法顾名思义可以理解为把整体展开成个体,在 ES5 中如果想把 一个 数组的 内容 拷贝到另 一个 数组中,可以使用 for 循环数组的每一项,然后 添加 到目标数组中去。但是如果使用展开语法就很方便地完成这个操作了。下面我们就来看看展开语法是如何使用的。
2. 从拷贝说起
2.1 数组拷贝
在 ES5 经常会遇到数组和对象的浅拷贝,我们都知道数组和对象都是引用类型,所以不能像字符串那样直接赋值,在 ES5 中数组和对象的拷贝都是通过循环来实现的,下面我们来看几个例子:
var arr1 = [ , , ] ; var arr2 = [ ] ; arr1 . forEach ( function ( value ) { arr2 . push ( value ) ; } ) console . log ( arr2 ) ; // [1, 2, 3]
上面的 代码 是把 arr1 数组中的项拷贝到 arr2 中去,还可以使用数组提供的 concat 和 slice 方法 来实现。
var arr1 = [ , , ] ; var arr2 = [ ] . concat ( arr1 ) ; var arr3 = arr1 . slice ( ) ; arr1 . push ( ) console . log ( arr1 ) ; //[1, 2, 3, 4] console . log ( arr2 ) ; //[1, 2, 3] console . log ( arr3 ) ; //[1, 2, 3]
在拷贝完后,对 arr1 数组 添加 元素,可以看到 arr2 和 arr3 没有发生变化,说明它们不是 一个 引用地址。这是 ES5 所提供的拷贝方式,那么 ES6 是如何简化的呢?
var arr1 = [ , , ] ; var arr2 = [ ... arr1 ] ; arr1 . push ( ) console . log ( arr1 ) ; //[1, 2, 3, 4] console . log ( arr2 ) ; //[1, 2, 3]
使用 ... 展开语法可以实现与上面 ES5 实现的相同 效果 ,而且比较简洁地表达了把 arr1 中的每一项展开放入 arr2 中。
2.2 字面量对象拷贝
上面说到了 ES5 和 ES6 数组拷贝的 一个 对比,那么针对字面量对象的拷贝二者又是怎么来实现的呢?
ES5 中针对字面量对象的拷贝方式比较少,没有数组提供的类似的 方法 可以使用,只能使用循环,但是还可以使用 JSON.stringify 和 JSON.parse 来实现,但是这个 方法 存在一些缺陷。 下面看 ES5 中字面量的拷贝实例:
let obj = { a : , b : } ; let cop y1 = { } ; for ( let key in obj ) { cop y1 [ key ] = obj [ key ] } let cop y2 = JSON . parse ( JSON . stringify ( obj ) )
上面的两种 方法 给出了 ES5 拷贝字面量对象的 方法 ,比较麻烦,也容易出错。ES6 给出了它的答案:
let obj = { a : , b : } ; let cop y = { ... obj } ;
使用展开语法对 obj 进行展开,完美地实现了拷贝过程。
Tips: 这里有必要说明一下,以上的 方法 都是浅拷贝(只拷贝数组和对象的第一层结构)的过程,对于数组和对象第一层以后的 内容 ,如果是引用类型的存储方式,则不会进行拷贝操作,也就是不会进行深拷贝。
3. 语法详情
上面通过拷贝初步了解了展开语法,这里我们给出展开语法的定义: 展开语法在 函数 调用 和构造数组时,将字符串和数组在语法层面展开;如果是对象时,将对象的表达式按照 key-value 的方式展开 。展开语法的使用主要有以下几种:
处理字符串、数组和字面量对象; 简化 函数 调用 时传参问题; 代替 apply 方法 。
3.1 在字符串中的使用
展开语法在处理字符串时,顾名思义可以把字符进行展开,从而得到 一个 每项都是单个字符串的数组,注意展开语法在字符串使用时,需要包裹在 [] 中才能生效。
const arr = [ ... 'imooc' ] ; console . log ( arr ) ; // ["i", "m", "o", "o", "c"]
在 ES5 中也有 方法 ,可以使用 split 方法 实现把字符串变成数组。
const arr = 'imooc' . split ( '' ) ; console . log ( arr ) ; // ["i", "m", "o", "o", "c"]
3.2 在数组中的使用
上面我们讲了 ES5 中对 一个 数组的拷贝,在数组的操作中还有 添加 、合并等操作的时候,需要 调用 数组的 slice () 、 concat () 、 unshift () 等 方法 ,或者组合使用这些 方法 。
const arr1 = [ , ] ; const arr2 = [ 'a' , ... arr1 ] ; const arr3 = [ ... arr1 , ... arr2 ] ; console . log ( arr2 ) ; // ['a', 1, 2] console . log ( arr3 ) ; // [1, 2, 'a', 1, 2]
上面的 代码 可以看出,展开语法有很多种不同的使用方式,我们可以把展开语法当成 一个 整体,直接放到想放到的位置上即可,扩展了操作数组的方式。
3.3 在字面量对象中的使用
和数组一样,展开语法在字面量对象中的使用方式也有很多种:
const obj1 = { a : , b : } ; const obj2 = { ... obj1 , c : } ; console . log ( obj2 ) ; // {a:1, b:2, c:30} const obj3 = { b : , c : } ; const obj4 = { ... obj2 , ... obj3 } ; // 合并对象 console . log ( obj4 ) ; // {a:1, b:20, c:30}
上面的 代码 可以看出,使用方式和数组基本一致,都是把数组或对象中的每一项展开到另 一个 数组或对象中去。
3.4 函数 调用 时传参问题
在 函数 调用 时经常会向 函数 中传递参数,但是,当我们的参数是数组中的项时,我们需要把数组中的每一项取出来,然后传入 函数 中,这样显得很麻烦,能不能有个方式直接把数组传入进去呢?首先我们看个求和的例子:
function sum ( x , y ) { return x + y ; } console . log ( sum ( , ) ) ; // 3 const data = [ , ] ; console . log ( sum ( data [ ] , data [ ] ) ) ; // 3
上面的 sum 是 一个 求和函数 ,接受两个参数,我们可以在 调用 时直接传递 2 个参数。但这个时候我们希望求 data 数组中的和,这个时候只能取出 data 中的每一项值传递到 函数 中去,这样无疑是 一个 很笨的 方法 ,在 ES5 的时候可以使用 apply() 对 函数 进行间接的 调用 解决 这个问题。
function sum ( x , y , z ) { return x + y + z ; } const data = [ , , ] ; console . log ( sum . apply ( null , data ) ) ; // 6
使用 apply() 的 方法 是 解决 了这个问题,但是可能会使我们理解 代码 增加 了难度。有了 ES6 的展开语法,这个问题就会轻而易举地 解决 了。
function sum ( x , y , z ) { return x + y + z ; } const data = [ , , ] ; console . log ( sum ( ... data ) ) ; // 6
上面的 方法 使用展开语法把 data 数组中的每一项进行展开,成为 sum 函数 中的三个参数。
4. 小结
本节通过数组和字面量的拷贝引入了 ES6 的展开语法的优势,又说到了在 函数 传参时的应用,可以总结以下几点:
可以把 ... 加数组或字面量当作数组或字面量中的一项,任意放入数组或字面量中不同的位置; 可以通过展开语法对数组和字面量进行浅拷贝; 在 函数 传参数直接把数组中的项进行展开就可以达到传递多个参数的目的。
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did91761