mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-28 21:32:20 +00:00
edit set-map
This commit is contained in:
parent
73be57cbeb
commit
91d44bdb6f
12
docs/fp.md
12
docs/fp.md
@ -1,6 +1,6 @@
|
|||||||
# 函数式编程
|
# 函数式编程
|
||||||
|
|
||||||
从一诞生,JavaScript语言就具有函数式编程的烙印。它将函数作为一种独立的数据类型,与其他数据类型处于完全平等的地位。在JavaScript语言中,你可以采用面向对象编程,也可以采用函数式编程。有人甚至说,JavaScript是有史以来第一种被大规模采用的函数式编程语言。
|
JavaScript语言从一诞生,就具有函数式编程的烙印。它将函数作为一种独立的数据类型,与其他数据类型处于完全平等的地位。在JavaScript语言中,你可以采用面向对象编程,也可以采用函数式编程。有人甚至说,JavaScript是有史以来第一种被大规模采用的函数式编程语言。
|
||||||
|
|
||||||
ES6的种种新增功能,使得函数式编程变得更方便、更强大。本章介绍ES6如何进行函数式编程。
|
ES6的种种新增功能,使得函数式编程变得更方便、更强大。本章介绍ES6如何进行函数式编程。
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ f.comp = (...fs) => {
|
|||||||
|
|
||||||
## 参数倒置
|
## 参数倒置
|
||||||
|
|
||||||
参数倒置(flip)指的是改变函数参数的顺序。
|
参数倒置(flip)指的是改变函数前两个参数的顺序。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var divide = (a, b) => a / b;
|
var divide = (a, b) => a / b;
|
||||||
@ -45,9 +45,13 @@ var flip = f.flip(divide);
|
|||||||
|
|
||||||
flip(10, 5) // 0.5
|
flip(10, 5) // 0.5
|
||||||
flip(1, 10) // 10
|
flip(1, 10) // 10
|
||||||
|
|
||||||
|
var three = (a, b, c) => [a, b, c];
|
||||||
|
var flip = f.flip(three);
|
||||||
|
flip(1, 2, 3); // => [2, 1, 3]
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,如果按照正常的参数顺序,10除以5等于2。但是,参数倒置以后得到的新函数,结果就是5除以10,结果得到0.5。
|
上面代码中,如果按照正常的参数顺序,10除以5等于2。但是,参数倒置以后得到的新函数,结果就是5除以10,结果得到0.5。如果原函数有3个参数,则只颠倒前两个参数的位置。
|
||||||
|
|
||||||
参数倒置的代码非常简单。
|
参数倒置的代码非常简单。
|
||||||
|
|
||||||
@ -55,7 +59,7 @@ flip(1, 10) // 10
|
|||||||
let f = {};
|
let f = {};
|
||||||
f.flip =
|
f.flip =
|
||||||
fn =>
|
fn =>
|
||||||
(...args) => fn.apply(null, args.reverse());
|
(a, b, ...args) => fn(b, a, ...args.reverse());
|
||||||
```
|
```
|
||||||
|
|
||||||
## 执行边界
|
## 执行边界
|
||||||
|
@ -1138,7 +1138,7 @@ function addOne(a){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
上面的函数不会进行尾调用优化,因为内层函数inner用到了,外层函数addOne的内部变量one。
|
上面的函数不会进行尾调用优化,因为内层函数`inner`用到了,外层函数`addOne`的内部变量`one`。
|
||||||
|
|
||||||
### 尾递归
|
### 尾递归
|
||||||
|
|
||||||
@ -1238,6 +1238,17 @@ factorial(5) // 120
|
|||||||
|
|
||||||
总结一下,递归本质上是一种循环操作。纯粹的函数式编程语言没有循环操作命令,所有的循环都用递归实现,这就是为什么尾递归对这些语言极其重要。对于其他支持“尾调用优化”的语言(比如Lua,ES6),只需要知道循环可以用递归代替,而一旦使用递归,就最好使用尾递归。
|
总结一下,递归本质上是一种循环操作。纯粹的函数式编程语言没有循环操作命令,所有的循环都用递归实现,这就是为什么尾递归对这些语言极其重要。对于其他支持“尾调用优化”的语言(比如Lua,ES6),只需要知道循环可以用递归代替,而一旦使用递归,就最好使用尾递归。
|
||||||
|
|
||||||
|
### 严格模式
|
||||||
|
|
||||||
|
ES6的尾调用优化只在严格模式下开启,正常模式是无效的。
|
||||||
|
|
||||||
|
这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。
|
||||||
|
|
||||||
|
- `arguments`:返回调用时函数的参数。
|
||||||
|
- `func.caller`:返回调用当前函数的那个函数。
|
||||||
|
|
||||||
|
尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效。
|
||||||
|
|
||||||
## 函数参数的尾逗号
|
## 函数参数的尾逗号
|
||||||
|
|
||||||
ES7有一个[提案](https://github.com/jeffmo/es-trailing-function-commas),允许函数的最后一个参数有尾逗号(trailing comma)。
|
ES7有一个[提案](https://github.com/jeffmo/es-trailing-function-commas),允许函数的最后一个参数有尾逗号(trailing comma)。
|
||||||
|
@ -328,7 +328,7 @@ ws.delete(window);
|
|||||||
ws.has(window); // false
|
ws.has(window); // false
|
||||||
```
|
```
|
||||||
|
|
||||||
WeakSet没有size属性,没有办法遍历它的成员。
|
WeakSet没有`size`属性,没有办法遍历它的成员。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
ws.size // undefined
|
ws.size // undefined
|
||||||
@ -338,11 +338,11 @@ ws.forEach(function(item){ console.log('WeakSet has ' + item)})
|
|||||||
// TypeError: undefined is not a function
|
// TypeError: undefined is not a function
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码试图获取size和forEach属性,结果都不能成功。
|
上面代码试图获取`size`和`forEach`属性,结果都不能成功。
|
||||||
|
|
||||||
WeakSet不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
|
WeakSet不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
|
||||||
|
|
||||||
下面是WeakMap的另一个例子。
|
下面是WeakSet的另一个例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const foos = new WeakSet()
|
const foos = new WeakSet()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user