@@ -481,3 +481,119 @@ Object.unobserve(o, observer);
481481```
482482
483483注意,Object.observe和Object.unobserve这两个方法不属于ES6,而是属于ES7的一部分。不过,Chrome浏览器从33版起就已经支持。
484+
485+ ## 对象的扩展运算符
486+
487+ 目前,ES7有一个[ 提案] ( https://github.com/sebmarkbage/ecmascript-rest-spread ) ,将rest参数/扩展运算符(...)引入对象。Babel转码器已经支持这项功能。
488+
489+ ** (1)Rest参数**
490+
491+ 如果Rest参数用于从一个对象取值,就等于将所有可遍历、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
492+
493+ ``` javascript
494+ let { x, y, ... z } = { x: 1 , y: 2 , a: 3 , b: 4 };
495+ x // 1
496+ y // 2
497+ z // { a: 3, b: 4 }
498+ ```
499+
500+ 上面代码中,变量z是Rest参数所在的对象。它获取等号右边的所有尚未读取的键(a和b),将它们和它们的值拷贝过来。
501+
502+ 注意,Rest参数的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么Rest参数拷贝的是这个值的引用,而不是这个值的副本。
503+
504+ ``` javascript
505+ let obj = { a: { b: 1 } };
506+ let { ... x } = obj;
507+ obj .a .b = 2 ;
508+ x .a .b // 2
509+ ```
510+
511+ 上面代码中,x是Rest参数,拷贝了对象obj的a属性。a属性引用了一个对象,修改这个对象的值,会影响到Rest参数对它的引用。
512+
513+ 另外,Rest参数不会拷贝继承自原型对象的属性。
514+
515+ ``` javascript
516+ let o1 = { a: 1 };
517+ let o2 = { b: 2 };
518+ o2 .__proto__ = o1;
519+ let o3 = { ... o2 };
520+ o3 // { b: 2 }
521+ ```
522+
523+ 上面代码中,对象o3是o2的复制,但是只复制了o2自身的属性,没有复制它的原型对象o1的属性。
524+
525+ ** (2)扩展运算符**
526+
527+ 如果扩展运算符用于一个对象,就会将该对象的所有可遍历属性,拷贝到一个新对象,然后返回这个新对象。
528+
529+ ``` javascript
530+ let z = { a: 3 , b: 4 };
531+ let n = { ... z };
532+ n // { a: 3, b: 4 }
533+ ```
534+
535+ 对象的扩展运算符,等同于使用` Object.assign ` 方法。
536+
537+ ``` javascript
538+ let aClone = { ... a };
539+ // 等同于
540+ let aClone = Object .assign ({}, a);
541+ ```
542+
543+ 扩展运算符可以用于合并两个对象。
544+
545+ ``` javascript
546+ let ab = { ... a, ... b };
547+ ```
548+
549+ 扩展运算符还可以用自定义属性,会在新对象之中,覆盖掉原有参数。
550+
551+ ``` javascript
552+ let aWithOverrides = { ... a, x: 1 , y: 2 };
553+ // 等同于
554+ let aWithOverrides = { ... a, ... { x: 1 , y: 2 } };
555+ // 等同于
556+ let x = 1 , y = 2 , aWithOverrides = { ... a, x, y };
557+ // 等同于
558+ let aWithOverrides = Object .assign ({}, a, { x: 1 , y: 2 });
559+ ```
560+
561+ 上面代码中,a对象的x属性和y属性,拷贝到新对象后会被覆盖掉。
562+
563+ 如果把自定义属性放在扩展运算符前面,就变成了设置新对象的默认属性值。
564+
565+ ``` javascript
566+ let aWithDefaults = { x: 1 , y: 2 , ... a };
567+ // 等同于
568+ let aWithDefaults = Object .assign ({}, { x: 1 , y: 2 }, a);
569+ // 等同于
570+ let aWithDefaults = Object .assign ({ x: 1 , y: 2 }, a);
571+ ```
572+
573+ 扩展运算符的参数对象之中,如果有取值函数` get ` ,这个函数是会执行的。
574+
575+ ``` javascript
576+ // 并不会抛出错误,因为x属性只是被定义,但没执行
577+ let aWithXGetter = {
578+ ... a,
579+ get x () {
580+ throws new Error (' not thrown yet' );
581+ }
582+ };
583+
584+ // 会抛出错误,因为x属性被执行了
585+ let runtimeError = {
586+ ... a,
587+ ... {
588+ get x () {
589+ throws new Error (' thrown now' );
590+ }
591+ }
592+ };
593+ ```
594+
595+ 如果扩展运算符的参数是null或undefined,这个两个值会被忽略,不会报错。
596+
597+ ``` javascript
598+ let emptyObject = { ... null, ... undefined }; // 不报错
599+ ```
0 commit comments