docs: consistent style

This commit is contained in:
Ika
2017-11-12 18:01:54 +08:00
parent eeba1984a8
commit e8fdb00040
30 changed files with 614 additions and 639 deletions
+9 -10
View File
@@ -237,7 +237,7 @@ foo(undefined, null)
(function (a, b, c = 5) {}).length // 2
```
上面代码中,`length`属性的返回值,等于函数的参数个数减去指定了默认值的参数个数。比如,上面最后一个函数,定义了3个参数,其中有一个参数`c`指定了默认值,因此`length`属性等于`3`减去`1`,最后得到`2`
上面代码中,`length`属性的返回值,等于函数的参数个数减去指定了默认值的参数个数。比如,上面最后一个函数,定义了 3 个参数,其中有一个参数`c`指定了默认值,因此`length`属性等于`3`减去`1`,最后得到`2`
这是因为`length`属性的含义是,该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。同理,后文的 rest 参数也不会计入`length`属性。
@@ -577,7 +577,7 @@ bar.name // "baz"
(new Function).name // "anonymous"
```
`bind`返回的函数,`name`属性值会加上`bound `前缀。
`bind`返回的函数,`name`属性值会加上`bound`前缀。
```javascript
function foo() {};
@@ -725,7 +725,7 @@ foo.call({ id: 42 });
// id: 42
```
上面代码中,`setTimeout`的参数是一个箭头函数,这个箭头函数的定义生效是在`foo`函数生成时,而它的真正执行要等到100毫秒后。如果是普通函数,执行时`this`应该指向全局对象`window`,这时应该输出`21`。但是,箭头函数导致`this`总是指向函数定义生效时所在的对象(本例是`{id: 42}`),所以输出的是`42`
上面代码中,`setTimeout`的参数是一个箭头函数,这个箭头函数的定义生效是在`foo`函数生成时,而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时`this`应该指向全局对象`window`,这时应该输出`21`。但是,箭头函数导致`this`总是指向函数定义生效时所在的对象(本例是`{id: 42}`),所以输出的是`42`
箭头函数可以让`setTimeout`里面的`this`,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子。
@@ -749,7 +749,7 @@ setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s2: 0
```
上面代码中,`Timer`函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的`this`绑定定义时所在的作用域(即`Timer`函数),后者的`this`指向运行时所在的作用域(即全局对象)。所以,3100毫秒之后,`timer.s1`被更新了3次,而`timer.s2`一次都没更新。
上面代码中,`Timer`函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的`this`绑定定义时所在的作用域(即`Timer`函数),后者的`this`指向运行时所在的作用域(即全局对象)。所以,3100 毫秒之后,`timer.s1`被更新了 3 次,而`timer.s2`一次都没更新。
箭头函数可以让`this`指向固定化,这种特性很有利于封装回调函数。下面是一个例子,DOM 事件的回调函数封装在一个对象里面。
@@ -792,7 +792,7 @@ function foo() {
}
```
上面代码中,转换后的ES5版本清楚地说明了,箭头函数里面根本没有自己的`this`,而是引用外层的`this`
上面代码中,转换后的 ES5 版本清楚地说明了,箭头函数里面根本没有自己的`this`,而是引用外层的`this`
请问下面的代码之中有几个`this`
@@ -898,7 +898,7 @@ mult2(plus1(5))
// 12
```
箭头函数还有一个功能,就是可以很方便地改写λ演算。
箭头函数还有一个功能,就是可以很方便地改写 λ 演算。
```javascript
// λ演算的写法
@@ -909,7 +909,7 @@ var fix = f => (x => f(v => x(x)(v)))
(x => f(v => x(x)(v)));
```
上面两种写法,几乎是一一对应的。由于λ演算对于计算机科学非常重要,这使得我们可以用ES6作为替代工具,探索计算机科学。
上面两种写法,几乎是一一对应的。由于 λ 演算对于计算机科学非常重要,这使得我们可以用 ES6 作为替代工具,探索计算机科学。
## 双冒号运算符
@@ -1178,7 +1178,7 @@ factorial(5) // 120
上面代码中,参数`total`有默认值`1`,所以调用时不用提供这个值。
总结一下,递归本质上是一种循环操作。纯粹的函数式编程语言没有循环操作命令,所有的循环都用递归实现,这就是为什么尾递归对这些语言极其重要。对于其他支持“尾调用优化”的语言(比如Lua,ES6),只需要知道循环可以用递归代替,而一旦使用递归,就最好使用尾递归。
总结一下,递归本质上是一种循环操作。纯粹的函数式编程语言没有循环操作命令,所有的循环都用递归实现,这就是为什么尾递归对这些语言极其重要。对于其他支持“尾调用优化”的语言(比如 Lua,ES6),只需要知道循环可以用递归代替,而一旦使用递归,就最好使用尾递归。
### 严格模式
@@ -1221,7 +1221,7 @@ sum(1, 100000)
// Uncaught RangeError: Maximum call stack size exceeded(…)
```
上面代码中,`sum`是一个递归函数,参数`x`是需要累加的值,参数`y`控制递归次数。一旦指定`sum`递归100000次,就会报错,提示超出调用栈的最大次数。
上面代码中,`sum`是一个递归函数,参数`x`是需要累加的值,参数`y`控制递归次数。一旦指定`sum`递归 100000 次,就会报错,提示超出调用栈的最大次数。
蹦床函数(trampoline)可以将递归执行转为循环执行。
@@ -1365,4 +1365,3 @@ try {
```
上面代码中,`JSON.parse`报错只有一种可能:解析失败。因此,可以不需要抛出的错误实例。