Thunk 函数
一、参数的求值策略
Thunk 函数在上世纪 60 年代就诞生了
当时计算机科学家研究编译器怎么些比较 优
其中有一个争论点时 求值策略,即函数的参数到底应该如何求值
var x = 1;
function f(m) {
return m * 2;
}
f(x + 5);
上面代码定义了一个函数 f,然后向它传入表达式 x+5。该表达式应该何时求值
传值调用 call by value
在进入函数体之前,先计算 x+5 的值,再将该值传入函数 f
C 语言就是采用这种策略
传名调用 call by name (传引用调用)
直接将表达式 x+5 传入函数体,只有在用到的时候再求值
传值调用
比较简单,可能存在性能损失。求值后可能完全用不到该参数- 常见的编程语言更倾向于
传名调用
二、Thunk 函数
编译器的 传名调用
实现,是将参数放到一个临时函数之中,再将这个临时函数传入函数体。
这个临时函数就叫做 Thunk 函数
function f(m) {
return m * 2;
}
f(x + 5);
// 等同于
var thunk = function () {
return x + 5;
};
function f(thunk) {
return thunk() * 2;
}
上述代码中,函数 f 的参数 x+5 被 thunk 函数替换掉了
需要使用原参数的地方对 Thunk 求值即可
这是 Thunk 函数的定义,它是 传名调用
的一种实现策略,用来替换某个表达式
三、Javascript 的 Thunk 函数
Javascript 是传值调用
Jacascript 的 Thunk 函数替换的不是表达式
而是多参数函数,将其替换成单参数的版本,且只接收回调函数作为参数
// 正常版本的readFile(多参数版本)
fs.readFile(fileName, callback);
// Thunk版本的readFile(单参数版本)
var readFileThunk = Thunk(fileName);
readFileThunk(callback);
var Thunk = function (fileName) {
return function (callback) {
return fs.readFile(fileName, callback);
};
};
fs 模块的 readFile 方法是一个多参数函数,两个参数分别为文件名和回调函数
经过转换器处理,它变成一个单参数函数,只接收回调函数作为参数,这个单参数版本,就叫做 Thunk 函数
四、Redux-thunk 中间件
Redux store 仅支持同步数据流
使用 thunk 等中间件可以帮助再 Redux 应用中实现异步
可以将 thunk 看作 store 的 dispatch()方法的封装器
使用 thunk action creator 派遣函数或 Promis,而不是返回 action 对象
参见