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

docs(symbol): edit symbol

This commit is contained in:
ruanyf 2017-04-21 13:58:23 +08:00
parent 15b962627e
commit b2182920bb
3 changed files with 29 additions and 29 deletions

View File

@ -723,7 +723,7 @@ let arr = [...obj]; // TypeError: Cannot spread non-iterable object
## 严格模式
从ES5开始函数内部可以设定为严格模式。
ES5 开始,函数内部可以设定为严格模式。
```javascript
function doSomething(a, b) {
@ -732,7 +732,7 @@ function doSomething(a, b) {
}
```
《ECMAScript 2016标准》做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
```javascript
// 报错
@ -762,7 +762,7 @@ const obj = {
};
```
这样规定的原因是,函数内部的严格模式,同时适用于函数体代码和函数参数代码。但是,函数执行的时候,先执行函数参数代码,然后再执行函数体代码。这样就有一个不合理的地方,只有从函数体代码之中,才能知道参数代码是否应该以严格模式执行,但是参数代码却应该先于函数体代码执行。
这样规定的原因是,函数内部的严格模式,同时适用于函数体和函数参数。但是,函数执行的时候,先执行函数参数,然后再执行函数体。这样就有一个不合理的地方,只有从函数体之中,才能知道参数是否应该以严格模式执行,但是参数却应该先于函数体执行。
```javascript
// 报错
@ -772,7 +772,7 @@ function doSomething(value = 070) {
}
```
上面代码中,参数`value`的默认值是八进制数`070`,但是严格模式下不能用前缀`0`表示八进制所以应该报错。但是实际上JavaScript引擎会先成功执行`value = 070`,然后进入函数体内部,发现需要用严格模式执行,这时才会报错。
上面代码中,参数`value`的默认值是八进制数`070`,但是严格模式下不能用前缀`0`表示八进制所以应该报错。但是实际上JavaScript 引擎会先成功执行`value = 070`,然后进入函数体内部,发现需要用严格模式执行,这时才会报错。
虽然可以先解析函数体代码,再执行参数代码,但是这样无疑就增加了复杂性。因此,标准索性禁止了这种用法,只要参数使用了默认值、解构赋值、或者扩展运算符,就不能显式指定严格模式。

View File

@ -2,7 +2,7 @@
## 属性的简洁表示法
ES6允许直接写入变量和函数作为对象的属性和方法。这样的书写更加简洁。
ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
```javascript
var foo = 'bar';
@ -1066,7 +1066,7 @@ y // undefined
z // 3
```
上面代码中,变量`x`是单纯的解构赋值,所以可以读取继承的属性;解构赋值产生的变量`y``z`,只能读取对象自身的属性,所以只有变量`z`可以赋值成功。
上面代码中,变量`x`是单纯的解构赋值,所以可以读取对象`o`继承的属性;变量`y``z`是双重解构赋值,只能读取对象`o`自身的属性,所以只有变量`z`可以赋值成功。
解构赋值的一个用处,是扩展某个函数的参数,引入其他操作。

View File

@ -2,11 +2,11 @@
## 概述
ES5的对象属性名都是字符串这容易造成属性名的冲突。比如你使用了一个他人提供的对象但又想为这个对象添加新的方法mixin模式新方法的名字就有可能与现有方法产生冲突。如果有一种机制保证每个属性的名字都是独一无二的就好了这样就从根本上防止属性名的冲突。这就是ES6引入Symbol的原因。
ES5 的对象属性名都是字符串这容易造成属性名的冲突。比如你使用了一个他人提供的对象但又想为这个对象添加新的方法mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入`Symbol`的原因。
ES6引入了一种新的原始数据类型Symbol表示独一无二的值。它是JavaScript语言的第七种数据类型前六种是Undefined、Null、布尔值Boolean、字符串String、数值Number、对象Object
ES6 引入了一种新的原始数据类型`Symbol`,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:`undefined``null`、布尔值Boolean、字符串String、数值Number、对象Object
Symbol值通过`Symbol`函数生成。这就是说对象的属性名现在可以有两种类型一种是原来就有的字符串另一种就是新增的Symbol类型。凡是属性名属于Symbol类型就都是独一无二的可以保证不会与其他属性名产生冲突。
Symbol 值通过`Symbol`函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
```javascript
let s = Symbol();
@ -15,11 +15,11 @@ typeof s
// "symbol"
```
上面代码中,变量`s`就是一个独一无二的值。`typeof`运算符的结果,表明变量`s`是Symbol数据类型而不是字符串之类的其他类型。
上面代码中,变量`s`就是一个独一无二的值。`typeof`运算符的结果,表明变量`s` Symbol 数据类型,而不是字符串之类的其他类型。
注意,`Symbol`函数前不能使用`new`命令否则会报错。这是因为生成的Symbol是一个原始类型的值不是对象。也就是说由于Symbol值不是对象所以不能添加属性。基本上它是一种类似于字符串的数据类型。
注意,`Symbol`函数前不能使用`new`命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
`Symbol`函数可以接受一个字符串作为参数表示对Symbol实例的描述主要是为了在控制台显示或者转为字符串时比较容易区分。
`Symbol`函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
```javascript
var s1 = Symbol('foo');
@ -32,7 +32,7 @@ s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
```
上面代码中,`s1``s2`是两个Symbol值。如果不加参数它们在控制台的输出都是`Symbol()`,不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。
上面代码中,`s1``s2`是两个 Symbol 值。如果不加参数,它们在控制台的输出都是`Symbol()`,不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。
如果 Symbol 的参数是一个对象,就会调用该对象的`toString`方法,将其转为字符串,然后才生成一个 Symbol 值。
@ -64,7 +64,7 @@ s1 === s2 // false
上面代码中,`s1``s2`都是`Symbol`函数的返回值,而且参数相同,但是它们是不相等的。
Symbol值不能与其他类型的值进行运算会报错。
Symbol 值不能与其他类型的值进行运算,会报错。
```javascript
var sym = Symbol('My symbol');
@ -75,7 +75,7 @@ var sym = Symbol('My symbol');
// TypeError: can't convert symbol to string
```
但是Symbol值可以显式转为字符串。
但是Symbol 值可以显式转为字符串。
```javascript
var sym = Symbol('My symbol');
@ -84,7 +84,7 @@ String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
```
另外Symbol值也可以转为布尔值但是不能转为数值。
另外Symbol 值也可以转为布尔值,但是不能转为数值。
```javascript
var sym = Symbol();
@ -99,9 +99,9 @@ Number(sym) // TypeError
sym + 2 // TypeError
```
## 作为属性名的Symbol
## 作为属性名的 Symbol
由于每一个Symbol值都是不相等的这意味着Symbol值可以作为标识符用于对象的属性名就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用能防止某一个键被不小心改写或覆盖。
由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
```javascript
var mySymbol = Symbol();
@ -123,9 +123,9 @@ Object.defineProperty(a, mySymbol, { value: 'Hello!' });
a[mySymbol] // "Hello!"
```
上面代码通过方括号结构和`Object.defineProperty`将对象的属性名指定为一个Symbol值。
上面代码通过方括号结构和`Object.defineProperty`,将对象的属性名指定为一个 Symbol 值。
注意Symbol值作为对象属性名时不能用点运算符。
注意Symbol 值作为对象属性名时,不能用点运算符。
```javascript
var mySymbol = Symbol();
@ -136,9 +136,9 @@ a[mySymbol] // undefined
a['mySymbol'] // "Hello!"
```
上面代码中,因为点运算符后面总是字符串,所以不会读取`mySymbol`作为标识名所指代的那个值,导致`a`的属性名实际上是一个字符串而不是一个Symbol值。
上面代码中,因为点运算符后面总是字符串,所以不会读取`mySymbol`作为标识名所指代的那个值,导致`a`的属性名实际上是一个字符串,而不是一个 Symbol 值。
同理在对象的内部使用Symbol值定义属性时Symbol值必须放在方括号之中。
同理,在对象的内部,使用 Symbol 值定义属性时Symbol 值必须放在方括号之中。
```javascript
let s = Symbol();
@ -150,7 +150,7 @@ let obj = {
obj[s](123);
```
上面代码中,如果`s`不放在方括号中,该属性的键名就是字符串`s`,而不是`s`所代表的那个Symbol值。
上面代码中,如果`s`不放在方括号中,该属性的键名就是字符串`s`,而不是`s`所代表的那个 Symbol 值。
采用增强的对象写法,上面代码的`obj`对象可以写得更简洁一些。
@ -160,7 +160,7 @@ let obj = {
};
```
Symbol类型还可以用于定义一组常量保证这组常量的值都是不相等的。
Symbol 类型还可以用于定义一组常量,保证这组常量的值都是不相等的。
```javascript
log.levels = {
@ -190,9 +190,9 @@ function getComplement(color) {
}
```
常量使用Symbol值最大的好处就是其他任何值都不可能有相同的值了因此可以保证上面的`switch`语句会按设计的方式工作。
常量使用 Symbol 值最大的好处,就是其他任何值都不可能有相同的值了,因此可以保证上面的`switch`语句会按设计的方式工作。
还有一点需要注意Symbol值作为属性名时该属性还是公开属性不是私有属性。
还有一点需要注意Symbol 值作为属性名时,该属性还是公开属性,不是私有属性。
## 实例:消除魔术字符串
@ -215,7 +215,7 @@ function getArea(shape, options) {
getArea('Triangle', { width: 100, height: 100 }); // 魔术字符串
```
上面代码中,字符串“Triangle”就是一个魔术字符串。它多次出现,与代码形成“强耦合”,不利于将来的修改和维护。
上面代码中,字符串`Triangle`就是一个魔术字符串。它多次出现,与代码形成“强耦合”,不利于将来的修改和维护。
常用的消除魔术字符串的方法,就是把它写成一个变量。
@ -237,9 +237,9 @@ function getArea(shape, options) {
getArea(shapeType.triangle, { width: 100, height: 100 });
```
上面代码中,我们把“Triangle”写成`shapeType`对象的`triangle`属性,这样就消除了强耦合。
上面代码中,我们把`Triangle`写成`shapeType`对象的`triangle`属性,这样就消除了强耦合。
如果仔细分析,可以发现`shapeType.triangle`等于哪个值并不重要,只要确保不会跟其他`shapeType`属性的值冲突即可。因此这里就很适合改用Symbol值。
如果仔细分析,可以发现`shapeType.triangle`等于哪个值并不重要,只要确保不会跟其他`shapeType`属性的值冲突即可。因此,这里就很适合改用 Symbol 值。
```javascript
const shapeType = {