第二章 一等公民的函数
最后更新于:2022-04-02 04:17:23
[TOC]
## 说明
函数可以像对待任何其他数据类型一样对待它们——把它们存在数组里,当作参数传递,赋值给变量...等等
## 例子
### 例子1
bad
```
const hi = name => `Hi ${name}`;
const greeting = name => hi(name);
```
good
```
const hi = name => `Hi ${name}`;
const greeting = hi =;
```
### 例子2
用一个函数把另一个函数包起来,目的仅仅是延迟执行,真的是非常糟糕的编程习惯
```
// 太傻了
const getServerStuff = callback => ajaxCall(json => callback(json));
// 等价于
ajaxCall(json => callback(json));
// 等价于
ajaxCall(callback);
// 等价于
const getServerStuff = callback => ajaxCall(callback);
// 等价于(最终)
const getServerStuff = ajaxCall
```
### 例子3
bad
```
const BlogController = {
index(posts) { return Views.index(posts); },
show(post) { return Views.show(post); },
create(attrs) { return Db.create(attrs); },
update(post, attrs) { return Db.update(post, attrs); },
destroy(post) { return Db.destroy(post); },
};
```
good
```
const BlogController = {
index: Views.index,
show: Views.show,
create: Db.create,
update: Db.update,
destroy: Db.destroy,
};
```
## 函数成功一等公民的好处
- 如果一个函数被不必要的包裹起来,那么函数变动时,被包裹的也需要变动
bad
```
httpGet('/post/2', json => renderPost(json));
// 改变
httpGet('/post/2', (json, err) => renderPost(json, err));
```
good
```
httpGet('/post/2', renderPost); // renderPost 将会在 httpGet 中调用,想要多少参数都行
```
- 增加函数的通用性
```
// 只针对当前的博客
const validArticles = articles =>
articles.filter(article => article !== null && article !== undefined),
// 对未来的项目更友好
const compact = xs => xs.filter(x => x !== null && x !== undefined);
```
- 在 js 中 需要注意 this
```
var fs = require('fs');
// 太可怕了
fs.readFile('freaky_friday.txt', Db.save);
// 好一点点
fs.readFile('freaky_friday.txt', Db.save.bind(Db));
```
> 把 Db 绑定(bind)到它自己身上以后,你就可以随心所欲地调用它的原型链式垃圾代码了
';