好得很程序员自学网

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

ES6+ 剩余参数

ES6+ 剩余参数

1. 前言

上节我们学习了展开语法,本节我们学习与之相反的操作 —— 剩余语法(Rest Syntax 也可以叫剩余参数)看起来和展开语法完全相同都是使用 ... 的语法糖,不同之处在于剩余参数用于解构数组和对象。从某种意义上说,剩余语法与展开语法是相反的:展开语法将数组展开为其中的各个元素,而剩余语法则是将多个元素收集起来成为 一个 整体。

2. 函数 参数

在讲解剩余参数前,我们先来看看,剩余参数在 函数 参数中都 解决 了哪些问题?为什么会引入剩余参数的概念?

在 ES5 中, 函数 经常会传入不定参数,在传入不定参数时,ES5 的给出的 解决方 案是通过 arguments 对象来 获取 函数 调用 时传递的参数。 arguments 对象不是 一个 数组,它是 一个 类数组对象,所谓类数组对象,就是指可以 通过索引 属性 访问元素 并且 拥有 length 属性 的对象。

一个 简单的类数组对象是长这样的:

  var  arrLike  =   { 
   :   'name'  , 
   :   'age'  , 
   :   'job'  , 
  length :  
 } 
 

而它所对应的数组应该是这样子的:

  var  arr  =   [  'name'  ,   'age'  ,   'job'  ]  ; 
 

这里我们说类数组对象与数组的性质相似,是因为类数组对象在 访问 、 赋值 、 获取 长度 上的操作与数组是一致的,具体 内容 可查阅相关的类数组使用。

在 函数 体中定义了 Arguments 对象,其包含 函数 的参数和其它 属性 ,以 arguments 变量来指代。下面我们看个实例:

  function   fn  (  )   { 
    console .  log  ( arguments )  ; 
 } 
 fn  (  'imooc'  ,   ,   'ES6'  ) 
 

在控制台中打印出上面的 代码 结果,如下图所示:在定义 函数 的时候没有给定参数,但是通过 arguments 对象可以拿到传入的参数。可以看到 arguments 中包含了 函数 传递的参数、length 等 属性 ,length 属性 表示的是实参的长度,即 调用 函数 的时候传入的参数个数。这样我们就对 arguments 对象有了一定的了解。

在 ES5 的开发模式下,想要使用传递的参数,则需要按位置把对应的参数取出来。尽管 arguments 是 一个 类数组且可遍历的变量,但它终究不是数组,它 不支持 数组 方法 ,因此我们不能 调用 arguments.forEeach (…) 等数组的 方法 。需要使用一些特殊的 方法 转换成数组使用,如:

  function   fn  (  )   { 
   var  arr  =   [  ]  . slice .  call  ( arguments )  ; 
  console .  log  ( arr ) 
 } 
 fn  (  'ES6'  )  ; 
 //  ["ES6"] 
 fn  (  'imooc'  ,   ,   'ES6'  )  ; 
 //  ["imooc", 7, "ES6"] 
 

终于借助 call 方法 把 arguments 转化成 一个 真正的数组了。但是这样无疑是 一个 繁琐的过程,而且不容易理解。这时 ES6 给出了它的完美 解决方 案 —— 剩余参数,那剩余参数是如何在 函数 传参中使用的呢?下面我们来看看实例:

  function   fn  (  ... args )   { 
  console .  log  ( args ) 
 } 
 fn  (  'ES6'  )  ; 
 //  ["ES6"] 
 fn  (  'imooc'  ,   ,   'ES6'  )  ; 
 //  ["imooc", 7, "ES6"] 
 

使用方式很简单在 函数 定义时使用 ... 紧接着跟 一个 收集的参数,这个收集的参数就是我们所传入不定参数的集合 —— 也就是数组。这样就很简单地摆脱了 arguments 的束缚。另外,还可以指定 一个 默 认的参数,如下示例:

  function   fn  ( name ,   ... args )   { 
  console .  log  ( name )  ;    // 基础参数 
  console .  log  ( args )  ;    // 剩下的参数组成的数组 
 } 
 fn  (  'ES6'  )  ; 
 //	'ES6' 
 //	[] 
 fn  (  'imooc'  ,   ,   'ES6'  )  ; 
 //  "imooc" 
 //	[7, "ES6"] 
 

上面的 代码 中给 函数 第 一个 参数,声明 一个 变量 name,剩余的参数会被 ... 收集成 一个 数组,这就是剩余参数。引入剩余参数就是为了能替代 函数 内部的 arguments ,由于 arguments 对象不具备数组的 方法 ,所以很多时候在使用之前要先转换成 一个 数组。而剩余参数本来就是 一个 数组,避免了这多余的一步,使用起来既优雅又自然。

2. 解构剩余参数

ES6 允许按照一定模式,从数组和对象中 提取值 ,并对变量进行赋值,这被称为解构(下节我们会讲到)。 比如如下 代码 :

  let  array  =   [  ,   ,   ] 
 let   [ a ,  b ,  c ]   =  array ; 
console .  log  ( a )  ; 				  // 1 
console .  log  ( b )  ; 				  // 2 
console .  log  ( c )  ; 				  // 3 
 

再比如如下 代码 :

  let  obj  =   { a :  ,  b :  ,  c :  } 
 let   { a ,  b ,  c }   =  obj ; 
console .  log  ( a )  ; 				 // 1 
console .  log  ( b )  ; 				 // 2 
console .  log  ( c )  ; 			   // 3 
 

上面的两个例子,就是数组和对象的解构赋值过程,在解构赋值时,可以使用剩余操作符。剩余操作符所操作的变量会匹配在解构赋值中所有其他变量未匹配到的 属性 。看如下示例:

  let   { a ,  b ,   ... others  }   =   { a :   ,   b :   ,   c :   ,   d :   ,   e :   } 
console .  log  ( a )  ; 					 // 1 
console .  log  ( b )  ; 					 // 2 
console .  log  ( others )  ; 		 // {c: 3,  d: 4,  e: 5} 
 

上面的 代码 中,a、b 会匹配对象中对应的值, ...others 则会收集匹配余下的 属性 值,并打包起来构造 一个 新的对象赋值给了 others 。

数组也可以通过剩余操作符,把剩余的元素打包成 一个 新的数组赋值给剩余 属性 , 代码 如下:

  let  array  =   [  ,   ,   ,   ,   ]  ; 
 let   [ a ,  b ,   ... others ]   =  array ; 
console .  log  ( a )  ; 					  // 1 
console .  log  ( b )  ; 					  // 2 
console .  log  ( others )  ; 		  // [3,4,5] 
 

在 函数 传参的时候也可以是和解构一起使用。如下所示。

  function   fun  (  ...  [ a ,  b ,  c ]  )   { 
   return  a  +  b  +  c ; 
 } 
 fun  (  '1'  )            // NaN (b 和 c 都是 undefined) 
 fun  (  ,   ,   )        // 6 
 fun  (  ,   ,   ,   )     // 6 多余的参数不会被 获取 到 
 

上面的 代码 中,a、b、c 会去解构传入参数, 加上 有剩余语法的作用,对应的值从数组中的项解构出来,在 函数 内部直接使用解构出来的参数即可。剩余语法看起来和展开语法完全相同,不同点在于,剩余参数用于解构数组和对象。

3. 小结

本节结合了 ES5 函数 中的 arguments 对象引入了为什么 ES6 会引入剩余参数的概念,可以看到剩余参数所带来的好处。本节 内容 可以总结以下几点:

@H_ 403 _839@剩余参数是为了能替代 函数 内部的 arguments 而引入的; @H_ 403 _839@和展开语法相反,剩余参数是将多个单个元素聚集起来形成 一个 单独的个体的过程。

查看更多关于ES6+ 剩余参数的详细内容...

  阅读:54次

上一篇

下一篇

第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的循环与可迭代对象示例详解