一、函数绑定”运算符(::)
“函数绑定”(function bind)运算符,用来取代call、apply、bind调用
函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面。
二、数组扩展运算符(…)
含义
扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
该运算符主要用于函数调用。
上面代码中,array.push(...items)和add(...numbers)这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。
扩展运算符与正常的函数参数可以结合使用,非常灵活。
扩展运算符后面还可以放置表达式。
如果扩展运算符后面是一个空数组,则不产生任何效果。
注意,扩展运算符如果放在括号中,JavaScript 引擎就会认为这是函数调用。如果这时不是函数调用,就会报错。
2 替代数组的 apply 方法
由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了。
扩展运算符取代apply方法的一个实际的例子,应用Math.max方法,简化求出一个数组最大元素的写法。
另一个例子是通过push函数,将一个数组添加到另一个数组的尾部
3 扩展运算符的应用
复制数组:
ES5 只能用变通方法来复制数组。
扩展运算符提供了复制数组的简便写法。
合并数组
扩展运算符提供了数组合并的新写法。
与解构赋值结合
扩展运算符可以与解构赋值结合起来,用于生成数组。
如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
函数的返回值
JavaScript 的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法
字符串
扩展运算符还可以将字符串转为真正的数组。
上面的写法,有一个重要的好处,那就是能够正确识别 32 位的 Unicode 字符。
实现了 Iterator 接口的对象
任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组。
Map 和 Set 结构, Generator 函数
扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构
Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。
三、对象的扩展运算符(…)
对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
上面代码中,变量z是解构赋值所在的对象。它获取等号右边的所有尚未读取的键(a和b),将它们连同值一起拷贝过来。
由于解构赋值要求等号右边是一个对象,所以如果等号右边是undefined或null,就会报错,因为它们无法转为对象。
解构赋值必须是最后一个参数,否则会报错。
对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
如果扩展运算符后面是一个空对象,则没有任何效果
如果扩展运算符后面不是对象,则会自动将其转为对象。
但是,如果扩展运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象。
对象的扩展运算符等同于使用Object.assign()方法
上面的例子只是拷贝了对象实例的属性,如果想完整克隆一个对象,还拷贝对象原型的属性,可以采用下面的写法。
扩展运算符可以用于合并两个对象。
如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖掉。
上面代码中,a对象的x属性和y属性,拷贝到新对象后会被覆盖掉。
这用来修改现有对象部分的属性就很方便了。
上面代码中,newVersion对象自定义了name属性,其他属性全部复制自previousVersion对象。
如果把自定义属性放在扩展运算符前面,就变成了设置新对象的默认属性值。
与数组的扩展运算符一样,对象的扩展运算符后面可以跟表达式。
扩展运算符的参数对象之中,如果有取值函数get,这个函数是会执行的。