Thunk

Thunk

https://en.wikipedia.org/wiki/Thunkjavascript

In computer programming, a thunk is a subroutine used to inject an additional calculation into another subroutine. Thunks are primarily used to delay a calculation until its result is needed, or toinsert operations at the beginning or end of the other subroutine. They have a variety of other applications in compiler code generation and modular programming.html

JS DEMO
java

// 'hypot' is a binary function
const hypot = (x, y) => Math.sqrt(x * x + y * y); // 'thunk' is a function that takes no arguments and, when invoked, performs a potentially expensive // operation (computing a square root, in this example) and/or causes some side-effect to occur const thunk = () => hypot(3, 4); // the thunk can then be passed around... doSomethingWithThunk(thunk); // ...or evaluated thunk(); // === 5

 

詞典

https://cn.bing.com/dict/search?q=thunk&FORM=BDVSP2&qpvt=Thunknode

  • 〔計〕形實替換程序;計算機的形式實在轉換程序
  • 網絡形實轉換程序;替換程式;出如今互操做中

結合上面的例子咱們理解爲, 將函數的參數提早進行綁定, 在須要的時候調用。git

綁定的過程, 就是將 實際參數 綁定到  形式參數上, 能夠對應到 形實替換的意思。github

 

阮大解釋

http://www.ruanyifeng.com/blog/2015/05/thunk.htmlweb

編譯器的"傳名調用"實現,每每是將參數放到一個臨時函數之中,再將這個臨時函數傳入函數體。這個臨時函數就叫作 Thunk 函數。npm

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 函數求值便可。json

這就是 Thunk 函數的定義,它是"傳名調用"的一種實現策略,用來替換某個表達式。網絡

 

JavaScript 語言是傳值調用,它的 Thunk 函數含義有所不一樣。在 JavaScript 語言中,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 函數。

 

Thunk實現

原理:

var Thunk = function(fn){ return function (){ var args = Array.prototype.slice.call(arguments); return function (callback){ args.push(callback); return fn.apply(this, args); } }; };


var readFileThunk = Thunk(fs.readFile); readFileThunk(fileA)(callback);
 

Node thunkify

https://github.com/tj/node-thunkify

var thunkify = require('thunkify'); var fs = require('fs'); var read = thunkify(fs.readFile); read('package.json', 'utf8')(function(err, str){ });

 

相似概念

curry

https://www.sitepoint.com/currying-in-functional-javascript/



var greetCurried = function(greeting) { return function(name) { console.log(greeting + ", " + name); }; };
var greetHello = greetCurried("Hello"); greetHello("Heidi"); //"Hello, Heidi" greetHello("Eddie"); //"Hello, Eddie" 

     使得函數更加可讀和彈性

More Readable And More Flexible

One of the advantages touted for functional JavaScript is shorter, tighter code that gets right to the point in the fewest lines possible, and with less repetition. Sometimes this can come at the expense of readability; until you’re familiar with the way the functional programming works, code written in this way can be harder to read and understand.

If you’ve come across the term currying before, but never knew what it meant, you can be forgiven for thinking of it as some exotic, spicy technique that you didn’t need to bother about. But currying is actually a very simple concept, and it addresses some familiar problems when dealing with function arguments, while opening up a range of flexible options for the developer.

https://www.npmjs.com/package/curry

var curry require('curry');
 
//-- creating a curried function is pretty
//-- straight forward:
var add curry(function(ab)return a + b });
 
//-- it can be called like normal:
add(12//= 3
 
//-- or, if you miss off any arguments,
//-- a new funtion that expects all (or some) of
//-- the remaining arguments will be created:
var add1 add(1);
add1(2//= 3;
 

 

bind

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

bind()方法建立一個新的函數,在調用時設置this關鍵字爲提供的值。並在調用新函數時,將給定參數列表做爲原函數的參數序列的前若干項。

var module = {  x: 42,  getX: function() {    return this.x;  }}var unboundGetX = module.getX;console.log(unboundGetX()); // The function gets invoked at the global scope// expected output: undefinedvar boundGetX = unboundGetX.bind(module);console.log(boundGetX());// expected output: 42

相關文章
相關標籤/搜索