mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2024-04-21 12:32:22 +00:00
修改symbol
This commit is contained in:
+43
-5
@@ -487,15 +487,53 @@ function* numbers() {
|
||||
|
||||
### (2)控制流管理
|
||||
|
||||
总结一下,如果某个操作非常耗时,可以把它拆成N步。
|
||||
如果有一个多步操作非常耗时,采用回调函数,可能会写成下面这样。
|
||||
|
||||
```javascript
|
||||
|
||||
step1(function (value1) {
|
||||
step2(value1, function(value2) {
|
||||
step3(value2, function(value3) {
|
||||
step4(value3, function(value4) {
|
||||
// Do something with value4
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
采用Promise改写上面的代码。
|
||||
|
||||
```javascript
|
||||
|
||||
Q.fcall(step1)
|
||||
.then(step2)
|
||||
.then(step3)
|
||||
.then(step4)
|
||||
.then(function (value4) {
|
||||
// Do something with value4
|
||||
}, function (error) {
|
||||
// Handle any error from step1 through step4
|
||||
})
|
||||
.done();
|
||||
|
||||
```
|
||||
|
||||
上面代码已经把回调函数,改成了直线执行的形式。Generator函数可以进一步改善代码运行流程。
|
||||
|
||||
```javascript
|
||||
|
||||
function* longRunningTask() {
|
||||
yield step1();
|
||||
yield step2();
|
||||
// ...
|
||||
yield stepN();
|
||||
try {
|
||||
var value1 = yield step1();
|
||||
var value2 = yield step2(value1);
|
||||
var value3 = yield step3(value2);
|
||||
var value4 = yield step4(value3);
|
||||
// Do something with value4
|
||||
} catch (e) {
|
||||
// Handle any error from step1 through step4
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+27
-1
@@ -67,7 +67,33 @@ class MySpecialTree {
|
||||
|
||||
```
|
||||
|
||||
上面代码是一个类部署Iterator接口的写法。`Symbol.iterator`是一个表达式,返回一个Symbol对象的iterator属性,这是一个类型为Symbol的特殊值,所以要放在方括号内。这里要注意,@@iterator的键名是`Symbol.iterator`,该方法执行后,返回一个当前对象的遍历器。
|
||||
上面代码是一个类部署Iterator接口的写法。`Symbol.iterator`是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为Symbol的特殊值,所以要放在方括号内(请参考Symbol一节)。这里要注意,@@iterator的键名是`Symbol.iterator`,键值是一个方法(函数),该方法执行后,返回一个当前对象的遍历器。
|
||||
|
||||
下面是为对象添加Iterator接口的例子。
|
||||
|
||||
```javascript
|
||||
|
||||
let obj = {
|
||||
data: [ 'hello', 'world' ],
|
||||
[Symbol.iterator]() {
|
||||
const self = this;
|
||||
let index = 0;
|
||||
return {
|
||||
next() {
|
||||
if (index < self.data.length) {
|
||||
return {
|
||||
value: self.data[index++],
|
||||
done: false
|
||||
};
|
||||
} else {
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
《数组的扩展》一章中提到,ES6对数组提供entries()、keys()和values()三个方法,就是返回三个遍历器。
|
||||
|
||||
|
||||
+78
-9
@@ -305,7 +305,20 @@ Object.getPrototypeOf(obj)
|
||||
|
||||
## Symbol
|
||||
|
||||
ES6引入了一种新的原始数据类型Symbol。它通过Symbol函数生成。
|
||||
ES6引入了一种新的原始数据类型Symbol,表示独一无二的ID。它通过Symbol函数生成。
|
||||
|
||||
```javascript
|
||||
|
||||
let symbol1 = Symbol();
|
||||
|
||||
typeof symbol
|
||||
// "symbol"
|
||||
|
||||
```
|
||||
|
||||
上面代码中,变量symbol1就是一个独一无二的ID。typeof运算符的结果,表明变量symbol1是Symbol数据类型,而不是字符串之类的其他类型。
|
||||
|
||||
Symbol函数可以接受一个字符串作为参数,表示Symbol实例的名称。
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -314,14 +327,33 @@ var mySymbol = Symbol('Test');
|
||||
mySymbol.name
|
||||
// Test
|
||||
|
||||
typeof mySymbol
|
||||
// "symbol"
|
||||
```
|
||||
|
||||
上面代码表示,Symbol函数的字符串参数,用来指定生成的Symbol的名称,可以通过name属性读取。之所以要新增name属性,是因为键名是Symbol类型,而有些场合需要一个字符串类型的值来指代这个键。
|
||||
|
||||
注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。
|
||||
|
||||
Symbol类型的值不能与其他类型的值进行运算,会报错。
|
||||
|
||||
```javascript
|
||||
|
||||
var sym = Symbol('My symbol');
|
||||
'' + sym
|
||||
// TypeError: Cannot convert a Symbol value to a string
|
||||
|
||||
```
|
||||
|
||||
上面代码表示,Symbol函数接受一个字符串作为参数,用来指定生成的Symbol的名称,可以通过name属性读取。typeof运算符的结果,表明Symbol是一种单独的数据类型。
|
||||
但是,Symbol类型的值可以转为字符串。
|
||||
|
||||
注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。
|
||||
```javascript
|
||||
|
||||
String(sym)
|
||||
// 'Symbol(My symbol)'
|
||||
|
||||
sym.toString()
|
||||
// 'Symbol(My symbol)'
|
||||
|
||||
```
|
||||
|
||||
symbol的最大特点,就是每一个Symbol都是不相等的,保证产生一个独一无二的值。
|
||||
|
||||
@@ -331,6 +363,10 @@ let w1 = Symbol();
|
||||
let w2 = Symbol();
|
||||
let w3 = Symbol();
|
||||
|
||||
w1 === w2 // false
|
||||
w1 === w3 // false
|
||||
w2 === w3 // false
|
||||
|
||||
function f(w) {
|
||||
switch (w) {
|
||||
case w1:
|
||||
@@ -346,18 +382,27 @@ function f(w) {
|
||||
|
||||
上面代码中,w1、w2、w3三个变量都等于`Symbol()`,但是它们的值是不相等的。
|
||||
|
||||
由于这种特点,Symbol类型适合作为标识符,用于对象的属性名,保证了属性名之间不会发生冲突。如果一个对象由多个模块构成,这样就不会出现同名的属性。另一种用途是,可以防止属性值被不小心修改。
|
||||
由于这种特点,Symbol类型适合作为标识符,用于对象的属性名,保证了属性名之间不会发生冲突。如果一个对象由多个模块构成,这样就不会出现同名的属性,也就防止了键值被不小心改写或覆盖。Symbol类型还可以用于定义一组常量,防止它们的值发生冲突。
|
||||
|
||||
```javascript
|
||||
|
||||
var a = {};
|
||||
var mySymbol = Symbol();
|
||||
|
||||
// 第一种写法
|
||||
var a = {};
|
||||
a[mySymbol] = 'Hello!';
|
||||
|
||||
//另一种写法
|
||||
// 第二种写法
|
||||
var a = {
|
||||
[mySymbol]: 123
|
||||
};
|
||||
|
||||
// 第三种写法
|
||||
var a = {};
|
||||
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
|
||||
|
||||
a[mySymbol] // "Hello!"
|
||||
|
||||
```
|
||||
|
||||
上面代码通过方括号结构和Object.defineProperty两种方法,将对象的属性名指定为一个Symbol值。
|
||||
@@ -387,6 +432,15 @@ a.size // 1
|
||||
|
||||
```
|
||||
|
||||
为Symbol函数添加一个参数,就可以引用了。
|
||||
|
||||
```javascript
|
||||
|
||||
let a = Map();
|
||||
a.set(Symbol('my_key'), 'Noise');
|
||||
|
||||
```
|
||||
|
||||
如果要在对象内部使用Symbol属性名,必须采用属性名表达式。
|
||||
|
||||
```javascript
|
||||
@@ -411,7 +465,7 @@ let obj = {
|
||||
|
||||
```
|
||||
|
||||
Symbol类型作为属性名,不会出现在for...in循环中,也不会被Object.getOwnPropertyNames方法返回,但是有一个对应的Object.getOwnPropertySymbols方法,以及Object.getOwnPropertyKeys方法都可以获取Symbol属性名。
|
||||
Symbol类型作为属性名,不会出现在for...in循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回,但是有一个对应的Object.getOwnPropertySymbols方法,以及Object.getOwnPropertyKeys方法都可以获取Symbol属性名。
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -433,6 +487,21 @@ Object.getOwnPropertySymbols(obj)
|
||||
|
||||
上面代码中,使用Object.getOwnPropertyNames方法得不到Symbol属性名,需要使用Object.getOwnPropertySymbols方法。
|
||||
|
||||
Reflect.ownKeys方法返回所有类型的键名。
|
||||
|
||||
```javascript
|
||||
|
||||
let obj = {
|
||||
[Symbol('my_key')]: 1,
|
||||
enum: 2,
|
||||
nonEnum: 3
|
||||
};
|
||||
|
||||
Reflect.ownKeys(obj)
|
||||
// [Symbol(my_key), 'enum', 'nonEnum']
|
||||
|
||||
```
|
||||
|
||||
## Proxy
|
||||
|
||||
所谓Proxy,可以理解成在目标对象之前,架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
- Dmitry Soshnikov, [ES6 Notes: Default values of parameters](http://dmitrysoshnikov.com/ecmascript/es6-notes-default-values-of-parameters/): 介绍参数的默认值
|
||||
- Mozilla Developer Network, [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet):介绍WeakSet数据结构
|
||||
- Mathias Bynens, [Unicode-aware regular expressions in ES6](https://mathiasbynens.be/notes/es6-unicode-regex): 详细介绍正则表达式的u修饰符
|
||||
- Axel Rauschmayer, [Symbols in ECMAScript 6](http://www.2ality.com/2014/12/es6-symbols.html): Symbol简介
|
||||
|
||||
## Iterator和Generator
|
||||
|
||||
|
||||
Reference in New Issue
Block a user