mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-28 21:32:20 +00:00
docs(let): edit let
This commit is contained in:
parent
4635e4598c
commit
f66e7cb391
@ -73,7 +73,9 @@ for (let i = 0; i < 3; i++) {
|
|||||||
|
|
||||||
### 不存在变量提升
|
### 不存在变量提升
|
||||||
|
|
||||||
`let`不像`var`那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。
|
`var`命令会发生”变量提升“现象,即变量可以在声明之前使用,值为`undefined`。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
|
||||||
|
|
||||||
|
为了纠正这种现象,`let`命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// var 的情况
|
// var 的情况
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
## 二进制和八进制表示法
|
## 二进制和八进制表示法
|
||||||
|
|
||||||
ES6提供了二进制和八进制数值的新的写法,分别用前缀`0b`(或`0B`)和`0o`(或`0O`)表示。
|
ES6 提供了二进制和八进制数值的新的写法,分别用前缀`0b`(或`0B`)和`0o`(或`0O`)表示。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
0b111110111 === 503 // true
|
0b111110111 === 503 // true
|
||||||
0o767 === 503 // true
|
0o767 === 503 // true
|
||||||
```
|
```
|
||||||
|
|
||||||
从ES5开始,在严格模式之中,八进制就不再允许使用前缀`0`表示,ES6进一步明确,要使用前缀`0o`表示。
|
从 ES5 开始,在严格模式之中,八进制就不再允许使用前缀`0`表示,ES6 进一步明确,要使用前缀`0o`表示。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 非严格模式
|
// 非严格模式
|
||||||
@ -613,6 +613,38 @@ ES6新增了6个三角函数方法。
|
|||||||
- `Math.acosh(x)` 返回`x`的反双曲余弦(inverse hyperbolic cosine)
|
- `Math.acosh(x)` 返回`x`的反双曲余弦(inverse hyperbolic cosine)
|
||||||
- `Math.atanh(x)` 返回`x`的反双曲正切(inverse hyperbolic tangent)
|
- `Math.atanh(x)` 返回`x`的反双曲正切(inverse hyperbolic tangent)
|
||||||
|
|
||||||
|
## Math.signbit()
|
||||||
|
|
||||||
|
`Math.sign()`用来判断一个值的正负,但是如果参数是`-0`,它会返回`-0`。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Math.sign(-0) // -0
|
||||||
|
```
|
||||||
|
|
||||||
|
这导致对于判断符号位的正负,`Math.sign()`不是很有用。JavaScript 内部使用64位浮点数(国际标准IEEE 754)表示数值,IEEE 754规定第一位是符号位,`0`表示正数,`1`表示负数。所以会有两种零,`+0`是符号位为`0`时的零值,`-0`是符号位为`1`时的零值。实际编程中,判断一个值是`+0`还是`-0`非常麻烦,因为它们是相等的。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
+0 === -0 // true
|
||||||
|
```
|
||||||
|
|
||||||
|
目前,有一个[提案](http://jfbastien.github.io/papers/Math.signbit.html),引入了`Math.signbit()`方法判断一个数的符号位是否设置了。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Math.signbit(2) //false
|
||||||
|
Math.signbit(-2) //true
|
||||||
|
Math.signbit(0) //false
|
||||||
|
Math.signbit(-0) //true
|
||||||
|
```
|
||||||
|
|
||||||
|
可以看到,该方法正确返回了`-0`的符号位是设置了的。
|
||||||
|
|
||||||
|
该方法的算法如下。
|
||||||
|
|
||||||
|
- 如果参数是`NaN`,返回`false`
|
||||||
|
- 如果参数是`-0`,返回`true`
|
||||||
|
- 如果参数是负值,返回`true`
|
||||||
|
- 其他情况返回`false`
|
||||||
|
|
||||||
## 指数运算符
|
## 指数运算符
|
||||||
|
|
||||||
ES2016 新增了一个指数运算符(`**`)。
|
ES2016 新增了一个指数运算符(`**`)。
|
||||||
@ -645,3 +677,4 @@ Math.pow(99, 99)
|
|||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,两个运算结果的最后一位有效数字是有差异的。
|
上面代码中,两个运算结果的最后一位有效数字是有差异的。
|
||||||
|
|
||||||
|
@ -1267,3 +1267,46 @@ let d = mix(c).with(a, b);
|
|||||||
|
|
||||||
出于完整性的考虑,`Object.getOwnPropertyDescriptors`进入标准以后,还会有`Reflect.getOwnPropertyDescriptors`方法。
|
出于完整性的考虑,`Object.getOwnPropertyDescriptors`进入标准以后,还会有`Reflect.getOwnPropertyDescriptors`方法。
|
||||||
|
|
||||||
|
## Null 传导运算符
|
||||||
|
|
||||||
|
编程实务中,如果读取对象内部的某个属性,往往需要判断一下该对象是否存在。比如,要读取`message.body.user.firstName`,安全的写法是写成下面这样。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const firstName = (message
|
||||||
|
&& message.body
|
||||||
|
&& message.body.user
|
||||||
|
&& message.body.user.firstName) || 'default';
|
||||||
|
```
|
||||||
|
|
||||||
|
这样的层层判断非常麻烦,因此现在有一个[提案](https://github.com/claudepache/es-optional-chaining),引入了“Null 传导运算符”(null propagation operator)`?.`,简化上面的写法。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const firstName = message?.body?.user?.firstName || 'default';
|
||||||
|
```
|
||||||
|
|
||||||
|
上面代码有三个`?.`运算符,只要其中一个返回`null`或`undefined`,就不再往下运算,而是返回`undefined`。
|
||||||
|
|
||||||
|
“Null 传导运算符”有四种用法。
|
||||||
|
|
||||||
|
- `obj?.prop` // 读取对象属性
|
||||||
|
- `obj?.[expr]` // 同上
|
||||||
|
- `func?.(...args)` // 函数或对象方法的调用
|
||||||
|
- `new C?.(...args)` // 构造函数的调用
|
||||||
|
|
||||||
|
传导运算符之所以写成`obj?.prop`,而不是`obj?prop`,是为了方便编译器能够区分三元运算符`?:`(比如`obj?prop:123`)。
|
||||||
|
|
||||||
|
下面是更多的例子。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 如果 a 是 null 或 undefined, 返回 undefined
|
||||||
|
// 否则返回 a?.b.c().d
|
||||||
|
a?.b.c().d
|
||||||
|
|
||||||
|
// 如果 a 是 null 或 undefined,下面的语句不产生任何效果
|
||||||
|
// 否则执行 a.b = 42
|
||||||
|
a?.b = 42
|
||||||
|
|
||||||
|
// 如果 a 是 null 或 undefined,下面的语句不产生任何效果
|
||||||
|
delete a?.b
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -413,9 +413,9 @@ re.flags // 's'
|
|||||||
|
|
||||||
## 后行断言
|
## 后行断言
|
||||||
|
|
||||||
JavaScript语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。
|
JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。
|
||||||
|
|
||||||
目前,有一个[提案](https://github.com/goyakin/es-regexp-lookbehind),在ES7加入后行断言。V8引擎4.9版已经支持,Chrome浏览器49版打开”experimental JavaScript features“开关(地址栏键入`about:flags`),就可以使用这项功能。
|
目前,有一个[提案](https://github.com/goyakin/es-regexp-lookbehind),引入后行断言。V8 引擎4.9版已经支持,Chrome 浏览器49版打开”experimental JavaScript features“开关(地址栏键入`about:flags`),就可以使用这项功能。
|
||||||
|
|
||||||
”先行断言“指的是,`x`只有在`y`前面才匹配,必须写成`/x(?=y)/`。比如,只匹配百分号之前的数字,要写成`/\d+(?=%)/`。”先行否定断言“指的是,`x`只有不在`y`前面才匹配,必须写成`/x(?!y)/`。比如,只匹配不在百分号之前的数字,要写成`/\d+(?!%)/`。
|
”先行断言“指的是,`x`只有在`y`前面才匹配,必须写成`/x(?=y)/`。比如,只匹配百分号之前的数字,要写成`/\d+(?=%)/`。”先行否定断言“指的是,`x`只有不在`y`前面才匹配,必须写成`/x(?!y)/`。比如,只匹配不在百分号之前的数字,要写成`/\d+(?!%)/`。
|
||||||
|
|
||||||
@ -426,16 +426,16 @@ JavaScript语言的正则表达式,只支持先行断言(lookahead)和先
|
|||||||
|
|
||||||
上面两个字符串,如果互换正则表达式,就会匹配失败。另外,还可以看到,”先行断言“括号之中的部分(`(?=%)`),是不计入返回结果的。
|
上面两个字符串,如果互换正则表达式,就会匹配失败。另外,还可以看到,”先行断言“括号之中的部分(`(?=%)`),是不计入返回结果的。
|
||||||
|
|
||||||
"后行断言"正好与"先行断言"相反,`x`只有在`y`后面才匹配,必须写成`/(?<=y)x/`。比如,只匹配美元符号之后的数字,要写成`/(?<=\$)\d+/`。”后行否定断言“则与”先行否定断言“相反,`x`只有不在`y`后面才匹配,必须写成`/(?<!y)x/`。比如,只匹配不在美元符号后面的数字,要写成`/(?<!\$)\d+/`。
|
“后行断言”正好与“先行断言”相反,`x`只有在`y`后面才匹配,必须写成`/(?<=y)x/`。比如,只匹配美元符号之后的数字,要写成`/(?<=\$)\d+/`。”后行否定断言“则与”先行否定断言“相反,`x`只有不在`y`后面才匹配,必须写成`/(?<!y)x/`。比如,只匹配不在美元符号后面的数字,要写成`/(?<!\$)\d+/`。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"]
|
/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"]
|
||||||
/(?<!\$)\d+/.exec('it’s is worth about €90') // ["90"]
|
/(?<!\$)\d+/.exec('it’s is worth about €90') // ["90"]
|
||||||
```
|
```
|
||||||
|
|
||||||
上面的例子中,"后行断言"的括号之中的部分(`(?<=\$)`),也是不计入返回结果。
|
上面的例子中,“后行断言”的括号之中的部分(`(?<=\$)`),也是不计入返回结果。
|
||||||
|
|
||||||
"后行断言"的实现,需要先匹配`/(?<=y)x/`的`x`,然后再回到左边,匹配`y`的部分。这种"先右后左"的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。
|
“后行断言”的实现,需要先匹配`/(?<=y)x/`的`x`,然后再回到左边,匹配`y`的部分。这种“先右后左”的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。
|
||||||
|
|
||||||
首先,”后行断言“的组匹配,与正常情况下结果是不一样的。
|
首先,”后行断言“的组匹配,与正常情况下结果是不一样的。
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user