From f66e7cb3912997b3ef4652c6e951639796d75e84 Mon Sep 17 00:00:00 2001 From: ruanyf Date: Tue, 7 Feb 2017 11:38:45 +0800 Subject: [PATCH] docs(let): edit let --- docs/let.md | 4 +++- docs/number.md | 37 +++++++++++++++++++++++++++++++++++-- docs/object.md | 43 +++++++++++++++++++++++++++++++++++++++++++ docs/regex.md | 10 +++++----- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/docs/let.md b/docs/let.md index 3a58bf2..73a609a 100644 --- a/docs/let.md +++ b/docs/let.md @@ -73,7 +73,9 @@ for (let i = 0; i < 3; i++) { ### 不存在变量提升 -`let`不像`var`那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。 +`var`命令会发生”变量提升“现象,即变量可以在声明之前使用,值为`undefined`。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。 + +为了纠正这种现象,`let`命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。 ```javascript // var 的情况 diff --git a/docs/number.md b/docs/number.md index 32ee464..ea152a1 100644 --- a/docs/number.md +++ b/docs/number.md @@ -2,14 +2,14 @@ ## 二进制和八进制表示法 -ES6提供了二进制和八进制数值的新的写法,分别用前缀`0b`(或`0B`)和`0o`(或`0O`)表示。 +ES6 提供了二进制和八进制数值的新的写法,分别用前缀`0b`(或`0B`)和`0o`(或`0O`)表示。 ```javascript 0b111110111 === 503 // true 0o767 === 503 // true ``` -从ES5开始,在严格模式之中,八进制就不再允许使用前缀`0`表示,ES6进一步明确,要使用前缀`0o`表示。 +从 ES5 开始,在严格模式之中,八进制就不再允许使用前缀`0`表示,ES6 进一步明确,要使用前缀`0o`表示。 ```javascript // 非严格模式 @@ -613,6 +613,38 @@ ES6新增了6个三角函数方法。 - `Math.acosh(x)` 返回`x`的反双曲余弦(inverse hyperbolic cosine) - `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 新增了一个指数运算符(`**`)。 @@ -645,3 +677,4 @@ Math.pow(99, 99) ``` 上面代码中,两个运算结果的最后一位有效数字是有差异的。 + diff --git a/docs/object.md b/docs/object.md index d97c231..1958b1c 100644 --- a/docs/object.md +++ b/docs/object.md @@ -1267,3 +1267,46 @@ let d = mix(c).with(a, b); 出于完整性的考虑,`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 +``` + diff --git a/docs/regex.md b/docs/regex.md index daa29fd..389c357 100644 --- a/docs/regex.md +++ b/docs/regex.md @@ -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+(?!%)/`。 @@ -426,16 +426,16 @@ JavaScript语言的正则表达式,只支持先行断言(lookahead)和先 上面两个字符串,如果互换正则表达式,就会匹配失败。另外,还可以看到,”先行断言“括号之中的部分(`(?=%)`),是不计入返回结果的。 -"后行断言"正好与"先行断言"相反,`x`只有在`y`后面才匹配,必须写成`/(?<=y)x/`。比如,只匹配美元符号之后的数字,要写成`/(?<=\$)\d+/`。”后行否定断言“则与”先行否定断言“相反,`x`只有不在`y`后面才匹配,必须写成`/(?