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

docs(symbol): edit symbol

This commit is contained in:
ruanyf 2016-11-25 13:12:10 +08:00
parent d9b5278347
commit 9e974525c1
4 changed files with 81 additions and 20 deletions

View File

@ -740,9 +740,28 @@ class B extends A {
}
```
上面代码中,子类`B`的构造函数之中的`super()`,代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。`super`虽然代表了父类`A`的构造函数,但是返回的是子类`B`的实例,即`super`内部的`this`指的是`B`,因此`super()`在这里相当于`A.prototype.constructor.call(this)`
上面代码中,子类`B`的构造函数之中的`super()`,代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。
注意,作为函数时,`super()`只能用在子类的构造函数之中,用在其他地方就会报错。
注意,`super`虽然代表了父类`A`的构造函数,但是返回的是子类`B`的实例,即`super`内部的`this`指的是`B`,因此`super()`在这里相当于`A.prototype.constructor.call(this)`
```javascript
class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {
constructor() {
super();
}
}
new A() // A
new B() // B
```
上面代码中,`new.target`指向当前正在执行的函数名。可以看到,在`super()`执行时,它指向的是子类`B`的构造函数,而不是父类`A`的构造函数。也就是说,`super()`内部的`this`指向的是`B`
作为函数时,`super()`只能用在子类的构造函数之中,用在其他地方就会报错。
```javascript
class A {}

View File

@ -223,6 +223,22 @@ var foo = 'bar';
var baz = { [foo]: 'abc'};
```
注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串`[object Object]`,这一点要特别小心。
```javascript
const keyA = {a: 1};
const keyB = {b: 2};
const myObject = {
[keyA]: 'valueA',
[keyB]: 'valueB'
};
myObject // Object {[object Object]: "valueB"}
```
上面代码中,`[keyA]``[keyB]`得到的都是`[object Object]`,所以`[keyB]`会把`[keyA]`覆盖掉,而`myObject`最后只有一个`[object Object]`属性。
## 方法的 name 属性
函数的`name`属性,返回函数名。对象方法也是函数,因此也有`name`属性。

View File

@ -115,6 +115,7 @@
- Keith Cirkel, [Metaprogramming in ES6: Symbols and why they're awesome](http://blog.keithcirkel.co.uk/metaprogramming-in-es6-symbols/): Symbol的深入介绍
- Axel Rauschmayer, [Customizing ES6 via well-known symbols](http://www.2ality.com/2015/09/well-known-symbols-es6.html)
- Derick Bailey, [Creating A True Singleton In Node.js, With ES6 Symbols](https://derickbailey.com/2016/03/09/creating-a-true-singleton-in-node-js-with-es6-symbols/)
- Das Surma, [How to read web specs Part IIa Or: ECMAScript Symbols](https://dassur.ma/things/reading-specs-2/): 介绍 Symbol 的规格
## Set和Map

View File

@ -34,6 +34,18 @@ s2.toString() // "Symbol(bar)"
上面代码中,`s1``s2`是两个Symbol值。如果不加参数它们在控制台的输出都是`Symbol()`,不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。
如果 Symbol 的参数是一个对象,就会调用该对象的`toString`方法,将其转为字符串,然后才生成一个 Symbol 值。
```javascript
const obj = {
toString() {
return 'abc';
}
};
const sym = Symbol(obj);
sym // Symbol(abc)
```
注意,`Symbol`函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的`Symbol`函数的返回值是不相等的。
```javascript
@ -44,8 +56,8 @@ var s2 = Symbol();
s1 === s2 // false
// 有参数的情况
var s1 = Symbol("foo");
var s2 = Symbol("foo");
var s1 = Symbol('foo');
var s2 = Symbol('foo');
s1 === s2 // false
```
@ -239,7 +251,7 @@ const shapeType = {
## 属性名的遍历
Symbol作为属性名该属性不会出现在`for...in``for...of`循环中,也不会被`Object.keys()``Object.getOwnPropertyNames()`返回。但是,它也不是私有属性,有一个`Object.getOwnPropertySymbols`方法可以获取指定对象的所有Symbol属性名。
Symbol 作为属性名,该属性不会出现在`for...in``for...of`循环中,也不会被`Object.keys()``Object.getOwnPropertyNames()``JSON.stringify()`返回。但是,它也不是私有属性,有一个`Object.getOwnPropertySymbols`方法,可以获取指定对象的所有 Symbol 属性名。
`Object.getOwnPropertySymbols`方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
@ -325,7 +337,7 @@ Object.getOwnPropertyNames(x) // ['0']
Object.getOwnPropertySymbols(x) // [Symbol(size)]
```
上面代码中对象x的size属性是一个Symbol值所以`Object.keys(x)``Object.getOwnPropertyNames(x)`都无法获取它。这就造成了一种非私有的内部方法的效果。
上面代码中,对象`x``size`属性是一个 Symbol 值,所以`Object.keys(x)``Object.getOwnPropertyNames(x)`都无法获取它。这就造成了一种非私有的内部方法的效果。
## Symbol.for()Symbol.keyFor()
@ -338,9 +350,9 @@ var s2 = Symbol.for('foo');
s1 === s2 // true
```
上面代码中s1和s2都是Symbol值但是它们都是同样参数的`Symbol.for`方法生成的,所以实际上是同一个值。
上面代码中,`s1``s2`都是 Symbol 值,但是它们都是同样参数的`Symbol.for`方法生成的,所以实际上是同一个值。
`Symbol.for()``Symbol()`这两种写法都会生成新的Symbol。它们的区别是前者会被登记在全局环境中供搜索后者不会。`Symbol.for()`不会每次调用就返回一个新的Symbol类型的值而是会先检查给定的key是否已经存在如果不存在才会新建一个值。比如如果你调用`Symbol.for("cat")`30次每次都会返回同一个Symbol值但是调用`Symbol("cat")`30次会返回30个不同的Symbol值。
`Symbol.for()``Symbol()`这两种写法都会生成新的Symbol。它们的区别是前者会被登记在全局环境中供搜索后者不会。`Symbol.for()`不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的`key`是否已经存在,如果不存在才会新建一个值。比如,如果你调用`Symbol.for("cat")`30次每次都会返回同一个 Symbol 值,但是调用`Symbol("cat")`30次会返回30个不同的Symbol值。
```javascript
Symbol.for("bar") === Symbol.for("bar")
@ -352,7 +364,7 @@ Symbol("bar") === Symbol("bar")
上面代码中,由于`Symbol()`写法没有登记机制,所以每次调用都会返回一个不同的值。
Symbol.keyFor方法返回一个已登记的Symbol类型值的key。
`Symbol.keyFor`方法返回一个已登记的 Symbol 类型值的`key`
```javascript
var s1 = Symbol.for("foo");
@ -578,6 +590,17 @@ String.prototype.replace(searchValue, replaceValue)
searchValue[Symbol.replace](this, replaceValue)
```
下面是一个例子。
```javascript
const x = {};
x[Symbol.replace] = (...s) => console.log(s);
'Hello'.replace(x, 'World') // ["Hello", "World"]
```
`Symbol.replace`方法会收到两个参数,第一个参数是`replace`方法正在作用的对象,上面例子是`Hello`,第二个参数是替换后的值,上面例子是`World`
### Symbol.search
对象的`Symbol.search`属性,指向一个方法,当该对象被`String.prototype.search`方法调用时,会返回该方法的返回值。
@ -681,12 +704,14 @@ String(obj) // 'str'
### Symbol.toStringTag
对象的`Symbol.toStringTag`属性,指向一个方法。在该对象上面调用`Object.prototype.toString`方法时,如果这个属性存在,它的返回值会出现在`toString`方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制`[object Object]``[object Array]`中object后面的那个字符串。
对象的`Symbol.toStringTag`属性,指向一个方法。在该对象上面调用`Object.prototype.toString`方法时,如果这个属性存在,它的返回值会出现在`toString`方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制`[object Object]``[object Array]``object`后面的那个字符串。
```javascript
// 例一
({[Symbol.toStringTag]: 'Foo'}.toString())
// "[object Foo]"
// 例二
class Collection {
get [Symbol.toStringTag]() {
return 'xxx';