好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ES6+ 展开语法

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 的展开语法的优势,又说到了在 函数 传参时的应用,可以总结以下几点:

可以把 ... 加数组或字面量当作数组或字面量中的一项,任意放入数组或字面量中不同的位置; 可以通过展开语法对数组和字面量进行浅拷贝; 在 函数 传参数直接把数组中的项进行展开就可以达到传递多个参数的目的。

查看更多关于ES6+ 展开语法的详细内容...

  阅读:49次

上一篇

下一篇

第1节:ES6+ 简介    第2节:ES6 环境配置    第3节:ES6+ let    第4节:ES6+ const    第5节:ES6+ 展开语法    第6节:ES6+ 剩余参数    第7节:ES6+ 解构赋值    第8节:ES6+ 模版字符串    第9节:ES6+ 箭头函数    第10节:ES6+ 数值扩展    第11节:ES6+ isFinite()&isNaN()    第12节:ES6+ Number 对象的方法    第13节:ES6+ Math 对象的扩展    第14节:ES6+ includes()    第15节:ES6+ 字符串的扩展    第16节:ES6+ startsWith()    第17节:ES6+ endsWith()    第18节:ES6+ repeat()    第19节:ES6+ padStart()    第20节:ES6+ padEnd()    第21节:ES6+ trim()    第22节:ES6+ Array.from()    第23节:ES6+ of()    第24节:ES6+ find()和findIndex()    第25节:ES6+ copyWithin()    第26节:ES6+ fill()    第27节:ES6+ isArray()    第28节:ES6+ 对象的扩展    第29节:ES6+ flat()    第30节:ES6+ 可选链操作符    第31节:ES6+ Object.is()    第32节:ES6+ Object.assign()    第33节:ES6+ Object.keys()    第34节:ES6+ Object.values()    第35节:ES6+ Object.entries()    第36节:ES6+ 数据结构扩展    第37节:ES6+ Set    第38节:ES6+ WeakSet    第39节:ES6+ Map    第40节:ES6+ WeakMap    第41节:ES6+ Symbol    第42节:ES6+ for...of    第43节:ES6+ 迭代协议    第44节:ES6+ 实现一个简版的 Promise    第45节:ES6+ Promise 基础    第46节:ES6+ Promise 进阶    第47节:ES6+ Generator 基础    第48节:ES6+ Generator 函数应用    第49节:ES6+ async/await    第50节:ES6+ Class 前置知识    第51节:ES6+ Class    第52节:ES6+ Proxy    第53节:ES6+ Reflect(一)    第54节:ES6+ Reflect(二)    第55节:ES6+ 模块化(一)    第56节:ES6+ 模块化(二)    第57节:ES6实战1-实现Vue3 reactive 源码    第58节:ES6实战2-实现 Vue3 effect 源码    第59节:ES6 实战2-封装请求    第60节:ES6+ 实战3-代码整洁之道    第61节:ES6 Map原理分析    第62节:ES6module语法加载importexport    第63节:ES6的循环与可迭代对象示例详解