js 中以 … 为前缀的几种用法详解
ES6 开始 ,js 新增了剩余参数语法 、展开语法等 ,它们有个共同之处就是都以 ... 这么个符号为前缀,好像很多地方都可以用到 ,但实际上又不是同一回事 ,容易让初学者晕头转向 。本篇就对目前笔者已知的 3 种关于 ... 用法的总结归纳 。
用法一:函数的剩余参数(Rest parameters)
在定义函数的时候 ,形参当中 ,最后一个参数(theArgs)如果以 ... 作为前缀 ,那么 theArgs 就会变为一个数组 ,调用该函数时 ,如果传入的实参数量大于等于定义函数时形参的数量 ,比如下面的例 1.1 ,形参定义了 3 个,却传入了 5 个实参 ,那么从 3 开始(包括) ,之后的实参都会被放入到 theArgs 中:
请注意,...theArgs 必须作为最后一个形参 ,不然会报语法错误:“SyntaxError: Rest parameter must be last formal parameter ” 。 除箭头函数外 ,函数内都有个 arguments 可以用来获取传递给函数的参数 。那么它和剩余参数有什么区别呢?
剩余参数,比如例 1.1 中的 theArgs 是个真数组 ,可以直接使用数组的方法 ,而 arguments 是一个类数组(array-like)对象 ,想要运用数组方法还得转成数组; 剩余参数只包含那些没有对应形参的实参 ,比如例 1.1 中的 3 、4 和 5 ,而 arguments 包含了传给函数的所有实参 。 arguments 可以通过 callee 属性获取当前 arguments 所在的函数 。其实 arguments 是早期的规范中为了方便获取传入函数的参数而存在的 ,ES6 之后 ,我们应当尽量使用剩余参数这种语法而不是 arguments 。
用法二:展开语法(Spread syntax)
展开语法又可以在 3 个地方使用:
1)调用函数时
剩余参数是在函数定义时形参里使用的 ,展开语法的用处之一则是在函数调用时 ,传入的实参里使用 。具体说就是将数组表达式或者 string 在语法层面展开作为实参传给函数 。比如有如下代码:
fn 接收 3 个参数,如果我们想把数组 arr 中的每个元素传给 fn ,在 ES6 之前可以利用 apply 实现:
有了展开语法 ,则可以直接将作为参数的数组 arr 展开,这样可以提高代码的可读性 :
展开语法还可以将字符串展开:
2)构造数组时
通过字面量方式构造数组时 ,也可以使用展开语法:
3)构造字面量对象时
除了构造数组 ,ES2018(ES9) 添加了新的特性使得构造对象的时候也可以运用展开语法,被展开的对象表达式将按 key-value 的方式展开 :
在构造对象字面量时 ,还可以把数组也放进去展开 ,比如在 MDN 上关于展开语法的说明中有这么个例子:
乍看上去迷迷糊糊的 ,可能的难点在于第 4 行代码的理解 ,它定义了一个函数 const merge = (...objects) => ({ ...objects } , 其中=> 左边的 ...objects 为函数的剩余参数语法 ,所以 objects 就是一个由 obj1 和 obj2 这两个对象组成的数组:[ { foo: bar, x: 42 }, { foo: baz, y: 13 } ];=>右边的 ...objects 用到的是展开语法 ,用于构造字面量对象 ,只不过因为 objects 是个数组 ,所以展开数组得到的对象的 key 为数组的下标,即 { ...objects } 得到的对象为:{ 0: { foo: bar, x: 42 }, 1: { foo: baz, y: 13 } }。
注意在调用函数或构造数组时使用展开语法只能用于可迭代对象 ,比如不能在构造数组时把一个对象放进去使用展开语法 。
展开语法其实是一种浅拷贝
在 MDN 文档还能看到这么一句话:
实际上, 展开语法和 Object.assign() 行为一致, 执行的都是浅拷贝(只遍历一层) 。
也就是说类似下面的例 2.4:
我们改变通过展开语法得到的 newObj 的深层属性 newObj.b.c = 我变了 时 ,会导致 obj.b.c 的值一同被修改。原因可以通过画内存表现图说明:
const newObj = { ...obj } 生成的 newObj,只是把堆内存中 obj 指向的地址为 0x100 这个对象整个复制了一份 ,生成了地址为 0x300 的新对象(注意这个新对象里 ,b 的值是一个内存地址),然后让 newObj 指向它 。如果我们更改了 newObj 的 a 属性或 b 属性的值 ,当然不会影响到 obj 对象 ,但是如果我们改变的是 newObj.b.c ,就会找到 0x200 这个对象并修改 ,自然会影响到 obj 对象 。
用法三:解构数组时
在对数组进行解构赋值时 ,我们可以使用剩余模式 ,将剩余数组赋值给一个变量 ,效果上类似于函数的剩余参数。比如下面例 3.1 中的 c:
以上就是js 中以 ... 为前缀的几种用法详解的详细内容 ,更多关于js ... 前缀用法的资料请关注本站其它相关文章!
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!