1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 18:32:22 +00:00

add object/扩展运算符

This commit is contained in:
ruanyf 2015-08-25 13:41:49 +08:00
parent 6d259c3388
commit 66932d0418
2 changed files with 120 additions and 0 deletions

View File

@ -227,6 +227,10 @@ let obj = {
```javascript
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 或者
NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
[...document.querySelectorAll('div')] // 可以执行了
```
如果Symbol.iterator方法返回的不是遍历器解释引擎将会报错。

View File

@ -481,3 +481,119 @@ Object.unobserve(o, observer);
```
注意Object.observe和Object.unobserve这两个方法不属于ES6而是属于ES7的一部分。不过Chrome浏览器从33版起就已经支持。
## 对象的扩展运算符
目前ES7有一个[提案](https://github.com/sebmarkbage/ecmascript-rest-spread)将rest参数/扩展运算符(...引入对象。Babel转码器已经支持这项功能。
**1Rest参数**
如果Rest参数用于从一个对象取值就等于将所有可遍历、但尚未被读取的属性分配到指定的对象上面。所有的键和它们的值都会拷贝到新对象上面。
```javascript
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
```
上面代码中变量z是Rest参数所在的对象。它获取等号右边的所有尚未读取的键a和b将它们和它们的值拷贝过来。
注意Rest参数的拷贝是浅拷贝即如果一个键的值是复合类型的值数组、对象、函数、那么Rest参数拷贝的是这个值的引用而不是这个值的副本。
```javascript
let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2;
x.a.b // 2
```
上面代码中x是Rest参数拷贝了对象obj的a属性。a属性引用了一个对象修改这个对象的值会影响到Rest参数对它的引用。
另外Rest参数不会拷贝继承自原型对象的属性。
```javascript
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let o3 = { ...o2 };
o3 // { b: 2 }
```
上面代码中对象o3是o2的复制但是只复制了o2自身的属性没有复制它的原型对象o1的属性。
**2扩展运算符**
如果扩展运算符用于一个对象,就会将该对象的所有可遍历属性,拷贝到一个新对象,然后返回这个新对象。
```javascript
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
```
对象的扩展运算符,等同于使用`Object.assign`方法。
```javascript
let aClone = { ...a };
// 等同于
let aClone = Object.assign({}, a);
```
扩展运算符可以用于合并两个对象。
```javascript
let ab = { ...a, ...b };
```
扩展运算符还可以用自定义属性,会在新对象之中,覆盖掉原有参数。
```javascript
let aWithOverrides = { ...a, x: 1, y: 2 };
// 等同于
let aWithOverrides = { ...a, ...{ x: 1, y: 2 } };
// 等同于
let x = 1, y = 2, aWithOverrides = { ...a, x, y };
// 等同于
let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
```
上面代码中a对象的x属性和y属性拷贝到新对象后会被覆盖掉。
如果把自定义属性放在扩展运算符前面,就变成了设置新对象的默认属性值。
```javascript
let aWithDefaults = { x: 1, y: 2, ...a };
// 等同于
let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a);
// 等同于
let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);
```
扩展运算符的参数对象之中,如果有取值函数`get`,这个函数是会执行的。
```javascript
// 并不会抛出错误因为x属性只是被定义但没执行
let aWithXGetter = {
...a,
get x() {
throws new Error('not thrown yet');
}
};
// 会抛出错误因为x属性被执行了
let runtimeError = {
...a,
...{
get x() {
throws new Error('thrown now');
}
}
};
```
如果扩展运算符的参数是null或undefined这个两个值会被忽略不会报错。
```javascript
let emptyObject = { ...null, ...undefined }; // 不报错
```