1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-28 04:42:21 +00:00

Merge branch 'gh-pages' of github.com:ruanyf/es6tutorial into gh-pages

This commit is contained in:
ruanyf 2016-05-15 12:07:44 +08:00
commit 73cff90609
5 changed files with 90 additions and 89 deletions

View File

@ -166,7 +166,8 @@ input.searchButton {
}
#content code {
padding-right: 5px;
padding-left: 3px;
padding-right: 3px;
color: #a6e22e;
font-size: 0.7rem;

View File

@ -96,7 +96,7 @@ const [v1, v2, ..., vN ] = array;
对于Set结构也可以使用数组的解构赋值。
```javascript
let [x, y, z] = new Set(["a", "b", "c"])
let [x, y, z] = new Set(["a", "b", "c"]);
x // "a"
```
@ -126,8 +126,8 @@ sixth // 5
var [foo = true] = [];
foo // true
[x, y = 'b'] = ['a'] // x='a', y='b'
[x, y = 'b'] = ['a', undefined] // x='a', y='b'
[x, y = 'b'] = ['a']; // x='a', y='b'
[x, y = 'b'] = ['a', undefined]; // x='a', y='b'
```
注意ES6内部使用严格相等运算符`===`),判断一个位置是否有值。所以,如果一个数组成员不严格等于`undefined`,默认值是不会生效的。
@ -145,7 +145,7 @@ x // null
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。
```javascript
function f(){
function f() {
console.log('aaa');
}
@ -321,7 +321,7 @@ x // null
如果解构失败,变量的值等于`undefined`
```javascript
var {foo} = {bar: 'baz'}
var {foo} = {bar: 'baz'};
foo // undefined
```
@ -329,7 +329,7 @@ foo // undefined
```javascript
// 报错
var {foo: {bar}} = {baz: 'baz'}
var {foo: {bar}} = {baz: 'baz'};
```
上面代码中,等号左边对象的`foo`属性,对应一个子对象。该子对象的`bar`属性,解构时会报错。原因很简单,因为`foo`这时等于`undefined`,再取子属性就会报错,请看下面的代码。
@ -426,7 +426,7 @@ function add([x, y]){
return x + y;
}
add([1, 2]) // 3
add([1, 2]); // 3
```
上面代码中,函数`add`的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量`x``y`。对于函数内部的代码来说,它们能感受到的参数就是`x``y`
@ -434,7 +434,7 @@ add([1, 2]) // 3
下面是另一个例子。
```javascript
[[1, 2], [3, 4]].map(([a, b]) => a + b)
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
```
@ -471,7 +471,7 @@ move(); // [0, 0]
`undefined`就会触发函数参数的默认值。
```javascript
[1, undefined, 3].map((x = 'yes') => x)
[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]
```
@ -583,11 +583,11 @@ var { foo, bar } = example();
```javascript
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3])
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1})
f({z: 3, y: 2, x: 1});
```
**4提取JSON数据**
@ -599,11 +599,11 @@ var jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
}
};
let { id, status, data: number } = jsonData;
console.log(id, status, number)
console.log(id, status, number);
// 42, "OK", [867, 5309]
```

View File

@ -21,9 +21,9 @@ b // 1
`for`循环的计数器就很合适使用let命令。
```javascript
for(let i = 0; i < arr.length; i++){}
for (let i = 0; i < arr.length; i++) {}
console.log(i)
console.log(i);
//ReferenceError: i is not defined
```
@ -189,14 +189,14 @@ ES5只有全局作用域和函数作用域没有块级作用域这带来
```javascript
var tmp = new Date();
function f(){
function f() {
console.log(tmp);
if (false){
if (false) {
var tmp = "hello world";
}
}
f() // undefined
f(); // undefined
```
上面代码中函数f执行后输出结果为`undefined`原因在于变量提升导致内层的tmp变量覆盖了外层的tmp变量。
@ -206,7 +206,7 @@ f() // undefined
```javascript
var s = 'hello';
for (var i = 0; i < s.length; i++){
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
@ -251,7 +251,7 @@ ES6允许块级作用域的任意嵌套。
```javascript
{{{{
let insane = 'Hello World';
{let insane = 'Hello World';}
{let insane = 'Hello World'}
}}}};
```
@ -294,7 +294,7 @@ function f() { console.log('I am outside!'); }
return a;
}
}
f() // 报错
f(); // 报错
```
上面代码中,块级作用域外部,无法调用块级作用域内部定义的函数。如果确实需要调用,就要像下面这样处理。
@ -305,9 +305,9 @@ let f;
let a = 'secret';
f = function () {
return a;
}
};
}
f() // "secret"
f(); // "secret"
```
ES5的严格模式规定函数只能在顶层作用域和函数内声明其他情况比如`if`代码块、循环代码块)的声明都会报错。
@ -342,7 +342,7 @@ if (true)
if (true) {
function f() {}
}
f() // ReferenceError: f is not defined
f(); // ReferenceError: f is not defined
```
上面代码中,函数`f`是在块级作用域内部声明的,外部是不可用的。
@ -425,7 +425,7 @@ foo.prop = 123;
foo.prop
// 123
foo = {} // TypeError: "foo" is read-only
foo = {}; // TypeError: "foo" is read-only
```
上面代码中,常量`foo`储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把`foo`指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。

View File

@ -24,7 +24,7 @@ ES6提供了二进制和八进制数值的新的写法分别用前缀`0b`
})() // Uncaught SyntaxError: Octal literals are not allowed in strict mode.
```
如果要将`0b``0x`前缀的字符串数值转为十进制,要使用`Number`方法。
如果要将`0b``0o`前缀的字符串数值转为十进制,要使用`Number`方法。
```javascript
Number('0b111') // 7
@ -141,7 +141,7 @@ Number.isInteger("15") // false
Number.isInteger(true) // false
```
ES5可以通过下面的代码部署Number.isInteger()。
ES5可以通过下面的代码部署`Number.isInteger()`
```javascript
(function (global) {
@ -196,7 +196,7 @@ Number.EPSILON.toFixed(20)
```javascript
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON
return Math.abs(left - right) < Number.EPSILON;
}
withinErrorMargin(0.1 + 0.2, 0.3)
// true
@ -286,9 +286,9 @@ function trusty (left, right, result) {
Number.isSafeInteger(right) &&
Number.isSafeInteger(result)
) {
return result
return result;
}
throw new RangeError('Operation cannot be trusted!')
throw new RangeError('Operation cannot be trusted!');
}
trusty(9007199254740993, 990, 9007199254740993 - 990)
@ -334,7 +334,7 @@ Math.trunc(); // NaN
```javascript
Math.trunc = Math.trunc || function(x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
}
};
```
### Math.sign()
@ -368,7 +368,7 @@ Math.sign = Math.sign || function(x) {
return x;
}
return x > 0 ? 1 : -1;
}
};
```
### Math.cbrt()
@ -449,9 +449,9 @@ Math.clz32(true) // 31
`Math.imul`方法返回两个数以32位带符号整数形式相乘的结果返回的也是一个32位的带符号整数。
```javascript
Math.imul(2, 4); // 8
Math.imul(-1, 8); // -8
Math.imul(-2, -2); // 4
Math.imul(2, 4) // 8
Math.imul(-1, 8) // -8
Math.imul(-2, -2) // 4
```
如果只考虑最后32位大多数情况下`Math.imul(a, b)``a * b`的结果是相同的,即该方法等同于`(a * b)|0`的效果超过32位的部分溢出。之所以需要部署这个方法是因为JavaScript有精度限制超过2的53次方的值无法精确表示。这就是说对于那些很大的数的乘法低位数值往往都是不精确的`Math.imul`方法可以返回正确的低位数值。
@ -471,11 +471,11 @@ Math.imul(0x7fffffff, 0x7fffffff) // 1
Math.fround方法返回一个数的单精度浮点数形式。
```javascript
Math.fround(0); // 0
Math.fround(1); // 1
Math.fround(1.337); // 1.3370000123977661
Math.fround(1.5); // 1.5
Math.fround(NaN); // NaN
Math.fround(0) // 0
Math.fround(1) // 1
Math.fround(1.337) // 1.3370000123977661
Math.fround(1.5) // 1.5
Math.fround(NaN) // NaN
```
对于整数来说,`Math.fround`方法返回结果不会有任何不同区别主要是那些无法用64个二进制位精确表示的小数。这时`Math.fround`方法会返回最接近这个小数的单精度浮点数。
@ -504,7 +504,7 @@ Math.hypot(-3); // 3
上面代码中3的平方加上4的平方等于5的平方。
如果参数不是数值Math.hypot方法会将其转为数值。只要有一个参数无法转为数值就会返回NaN。
如果参数不是数值,`Math.hypot`方法会将其转为数值。只要有一个参数无法转为数值就会返回NaN。
### 对数方法
@ -515,9 +515,9 @@ ES6新增了4个对数相关方法。
`Math.expm1(x)`返回e<sup>x</sup> - 1`Math.exp(x) - 1`
```javascript
Math.expm1(-1); // -0.6321205588285577
Math.expm1(0); // 0
Math.expm1(1); // 1.718281828459045
Math.expm1(-1) // -0.6321205588285577
Math.expm1(0) // 0
Math.expm1(1) // 1.718281828459045
```
对于没有部署这个方法的环境,可以用下面的代码模拟。
@ -533,10 +533,10 @@ Math.expm1 = Math.expm1 || function(x) {
`Math.log1p(x)`方法返回`1 + x`的自然对数,即`Math.log(1 + x)`。如果`x`小于-1返回`NaN`
```javascript
Math.log1p(1); // 0.6931471805599453
Math.log1p(0); // 0
Math.log1p(-1); // -Infinity
Math.log1p(-2); // NaN
Math.log1p(1) // 0.6931471805599453
Math.log1p(0) // 0
Math.log1p(-1) // -Infinity
Math.log1p(-2) // NaN
```
对于没有部署这个方法的环境,可以用下面的代码模拟。
@ -549,14 +549,14 @@ Math.log1p = Math.log1p || function(x) {
**3Math.log10()**
`Math.log10(x)`返回以10为底的x的对数。如果x小于0则返回NaN。
`Math.log10(x)`返回以10为底的`x`的对数。如果`x`小于0则返回NaN。
```javascript
Math.log10(2); // 0.3010299956639812
Math.log10(1); // 0
Math.log10(0); // -Infinity
Math.log10(-2); // NaN
Math.log10(100000); // 5
Math.log10(2) // 0.3010299956639812
Math.log10(1) // 0
Math.log10(0) // -Infinity
Math.log10(-2) // NaN
Math.log10(100000) // 5
```
对于没有部署这个方法的环境,可以用下面的代码模拟。
@ -569,15 +569,15 @@ Math.log10 = Math.log10 || function(x) {
**4Math.log2()**
`Math.log2(x)`返回以2为底的x的对数。如果x小于0则返回NaN。
`Math.log2(x)`返回以2为底的`x`的对数。如果`x`小于0则返回NaN。
```javascript
Math.log2(3) // 1.584962500721156
Math.log2(2) // 1
Math.log2(1) // 0
Math.log2(0) // -Infinity
Math.log2(-2) // NaN
Math.log2(1024) // 10
Math.log2(3) // 1.584962500721156
Math.log2(2) // 1
Math.log2(1) // 0
Math.log2(0) // -Infinity
Math.log2(-2) // NaN
Math.log2(1024) // 10
Math.log2(1 << 29) // 29
```
@ -593,12 +593,12 @@ Math.log2 = Math.log2 || function(x) {
ES6新增了6个三角函数方法。
- Math.sinh(x) 返回x的双曲正弦hyperbolic sine
- Math.cosh(x) 返回x的双曲余弦hyperbolic cosine
- Math.tanh(x) 返回x的双曲正切hyperbolic tangent
- Math.asinh(x) 返回x的反双曲正弦inverse hyperbolic sine
- Math.acosh(x) 返回x的反双曲余弦inverse hyperbolic cosine
- Math.atanh(x) 返回x的反双曲正切inverse hyperbolic tangent
- `Math.sinh(x)` 返回`x`的双曲正弦hyperbolic sine
- `Math.cosh(x)` 返回`x`的双曲余弦hyperbolic cosine
- `Math.tanh(x)` 返回`x`的双曲正切hyperbolic tangent
- `Math.asinh(x)` 返回`x`的反双曲正弦inverse hyperbolic sine
- `Math.acosh(x)` 返回`x`的反双曲余弦inverse hyperbolic cosine
- `Math.atanh(x)` 返回`x`的反双曲正切inverse hyperbolic tangent
## 指数运算符

View File

@ -58,13 +58,13 @@ ES6对正则表达式添加了`u`修饰符含义为“Unicode模式”
// true
```
上面代码中,“\uD83D\uDC2A”是一个四个字节的UTF-16编码代表一个字符。但是ES5不支持四个字节的UTF-16编码会将其识别为两个字符导致第二行代码结果为true。加了u修饰符以后ES6就会识别其为一个字符所以第一行代码结果为`false`
上面代码中,`\uD83D\uDC2A`是一个四个字节的UTF-16编码代表一个字符。但是ES5不支持四个字节的UTF-16编码会将其识别为两个字符导致第二行代码结果为`true`。加了`u`修饰符以后ES6就会识别其为一个字符所以第一行代码结果为`false`
一旦加上u修饰符号就会修改下面这些正则表达式的行为。
一旦加上`u`修饰符号,就会修改下面这些正则表达式的行为。
**1点字符**
点(.)字符在正则表达式中,含义是除了换行符以外的任意单个字符。对于码点大于`0xFFFF`的Unicode字符点字符不能识别必须加上u修饰符。
点(`.`)字符在正则表达式中,含义是除了换行符以外的任意单个字符。对于码点大于`0xFFFF`的Unicode字符点字符不能识别必须加上`u`修饰符。
```javascript
var s = '𠮷';
@ -73,11 +73,11 @@ var s = '𠮷';
/^.$/u.test(s) // true
```
上面代码表示如果不添加u修饰符正则表达式就会认为字符串为两个字符从而匹配失败。
上面代码表示,如果不添加`u`修饰符,正则表达式就会认为字符串为两个字符,从而匹配失败。
**2Unicode字符表示法**
ES6新增了使用大括号表示Unicode字符这种表示法在正则表达式中必须加上u修饰符才能识别。
ES6新增了使用大括号表示Unicode字符这种表示法在正则表达式中必须加上`u`修饰符,才能识别。
```javascript
/\u{61}/.test('a') // false
@ -85,11 +85,11 @@ ES6新增了使用大括号表示Unicode字符这种表示法在正则表达
/\u{20BB7}/u.test('𠮷') // true
```
上面代码表示如果不加u修饰符正则表达式无法识别`\u{61}`这种表示法只会认为这匹配61个连续的u。
上面代码表示,如果不加`u`修饰符,正则表达式无法识别`\u{61}`这种表示法只会认为这匹配61个连续的`u`
**3量词**
使用u修饰符后所有量词都会正确识别大于码点大于`0xFFFF`的Unicode字符。
使用`u`修饰符后,所有量词都会正确识别大于码点大于`0xFFFF`的Unicode字符。
```javascript
/a{2}/.test('aa') // true
@ -98,24 +98,24 @@ ES6新增了使用大括号表示Unicode字符这种表示法在正则表达
/𠮷{2}/u.test('𠮷𠮷') // true
```
另外只有在使用u修饰符的情况下Unicode表达式当中的大括号才会被正确解读否则会被解读为量词。
另外,只有在使用`u`修饰符的情况下Unicode表达式当中的大括号才会被正确解读否则会被解读为量词。
```javascript
/^\u{3}$/.test('uuu') // true
```
上面代码中由于正则表达式没有u修饰符所以大括号被解读为量词。加上u修饰符就会被解读为Unicode表达式。
上面代码中,由于正则表达式没有`u`修饰符,所以大括号被解读为量词。加上`u`修饰符就会被解读为Unicode表达式。
**4预定义模式**
u修饰符也影响到预定义模式能否正确识别码点大于`0xFFFF`的Unicode字符。
`u`修饰符也影响到预定义模式,能否正确识别码点大于`0xFFFF`的Unicode字符。
```javascript
/^\S$/.test('𠮷') // false
/^\S$/u.test('𠮷') // true
```
上面代码的`\S`是预定义模式匹配所有不是空格的字符。只有加了u修饰符它才能正确匹配码点大于0xFFFF的Unicode字符。
上面代码的`\S`是预定义模式,匹配所有不是空格的字符。只有加了`u`修饰符,它才能正确匹配码点大于`0xFFFF`的Unicode字符。
利用这一点,可以写出一个正确返回字符串长度的函数。
@ -133,7 +133,7 @@ codePointLength(s) // 2
**5i修饰符**
有些Unicode字符的编码不同但是字型很相近比如\u004B与\u212A都是大写的K。
有些Unicode字符的编码不同但是字型很相近比如`\u004B``\u212A`都是大写的K。
```javascript
/[a-z]/i.test('\u212A') // false
@ -160,7 +160,7 @@ r1.exec(s) // ["aa"]
r2.exec(s) // null
```
上面代码有两个正则表达式,一个使用`g`修饰符,另一个使用`y`修饰符。这两个正则表达式各执行了两次,第一次执行的时候,两者行为相同,剩余字符串都是`_aa_a`。由于g修饰没有位置要求所以第二次执行会返回结果而y修饰符要求匹配必须从头部开始所以返回`null`
上面代码有两个正则表达式,一个使用`g`修饰符,另一个使用`y`修饰符。这两个正则表达式各执行了两次,第一次执行的时候,两者行为相同,剩余字符串都是`_aa_a`。由于`g`修饰没有位置要求,所以第二次执行会返回结果,而`y`修饰符要求匹配必须从头部开始,所以返回`null`
如果改一下正则表达式,保证每次都能头部匹配,`y`修饰符就会返回结果了。
@ -197,7 +197,7 @@ REGEX.exec('xaxa') // null
上面代码中,`lastIndex`属性指定每次搜索的开始位置,`g`修饰符从这个位置开始向后搜索,直到发现匹配为止。
y修饰符同样遵守`lastIndex`属性,但是要求必须在`lastIndex`指定的位置发现匹配。
`y`修饰符同样遵守`lastIndex`属性,但是要求必须在`lastIndex`指定的位置发现匹配。
```javascript
const REGEX = /a/y;
@ -217,16 +217,16 @@ match.index // 3
REGEX.lastIndex // 4
```
进一步说,`y`修饰符号隐含了头部匹配的标志&#710;
进一步说,`y`修饰符号隐含了头部匹配的标志`^`
```javascript
/b/y.exec('aba')
// null
```
上面代码由于不能保证头部匹配,所以返回`null``y`修饰符的设计本意,就是让头部匹配的标志&#710;在全局匹配中都有效。
上面代码由于不能保证头部匹配,所以返回`null``y`修饰符的设计本意,就是让头部匹配的标志`^`在全局匹配中都有效。
`split`方法中使用y修饰符原字符串必须以分隔符开头。这也意味着只要匹配成功数组的第一个成员肯定是空字符串。
`split`方法中使用`y`修饰符,原字符串必须以分隔符开头。这也意味着,只要匹配成功,数组的第一个成员肯定是空字符串。
```javascript
// 没有找到匹配
@ -298,7 +298,7 @@ tokenize(TOKEN_G, '3x + 4')
## sticky属性
与y修饰符相匹配ES6的正则对象多了sticky属性表示是否设置了y修饰符。
`y`修饰符相匹配ES6的正则对象多了`sticky`属性,表示是否设置了`y`修饰符。
```javascript
var r = /hello\d/y;
@ -307,7 +307,7 @@ r.sticky // true
## flags属性
ES6为正则表达式新增了flags属性会返回正则表达式的修饰符。
ES6为正则表达式新增了`flags`属性,会返回正则表达式的修饰符。
```javascript
// ES5的source属性
@ -335,7 +335,7 @@ escapeRegExp(str)
// "\/path\/to\/resource\.html\?search=query"
```
上面代码中str是一个正常字符串必须使用反斜杠对其中的特殊字符转义才能用来作为一个正则匹配的模式。
上面代码中,`str`是一个正常字符串,必须使用反斜杠对其中的特殊字符转义,才能用来作为一个正则匹配的模式。
已经有[提议](https://esdiscuss.org/topic/regexp-escape)将这个需求标准化作为RegExp对象的静态方法[RegExp.escape()](https://github.com/benjamingr/RexExp.escape)放入ES7。2015年7月31日TC39认为这个方法有安全风险又不愿这个方法变得过于复杂没有同意将其列入ES7但这不失为一个真实的需求。
@ -358,7 +358,7 @@ var regex = new RegExp(RegExp.escape(str), 'g');
assert.equal(String(regex), '/hello\. how are you\?/g');
```
目前该方法可以用上文的escapeRegExp函数或者垫片模块[regexp.escape](https://github.com/ljharb/regexp.escape)实现。
目前,该方法可以用上文的`escapeRegExp`函数或者垫片模块[regexp.escape](https://github.com/ljharb/regexp.escape)实现。
```javascript
var escape = require('regexp.escape');