對象是包含行爲的數據,閉包是包含數據的行爲。html
閉包就是可以讀取其餘函數內部變量的函數,也可讓內部的局部變量經過閉包暴露給外部函數,因此本質上閉包就是將函數內部和函數外部鏈接起來的一座橋樑。git
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000
//f2中用了f1中的局部變量,而f2被賦給了一個全局變量,這致使f2始終在內存中,而f2的存在依賴於f1,所以f1也始終在內存中,不會在調用結束後,被垃圾回收機制(garbage collection)回收。這樣就能夠達到局部變量在屢次調用閉包時候共享的目的。
//這段代碼中另外一個值得注意的地方,就是"nAdd=function(){n+=1}"這一行,首先在nAdd前面沒有使用var關鍵字,所以nAdd是一個全局變量,而不是局部變量。其次,nAdd的值是一個匿名函數(anonymous function),而這個匿名函數自己也是一個閉包,因此nAdd至關因而一個setter,能夠在函數外部對函數內部的局部變量進行操做。
//若是你能理解下面兩段代碼的運行結果,應該就算理解閉包的運行機制了。 //代碼片斷一 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); //代碼片斷二 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());
一個介紹js函數式編程的gitbook https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/編程
// 把整個應用裏的全部 httpGet 調用都改爲這樣,能夠傳遞 err 參數。 httpGet('/post/2', function(json, err){ return renderPost(json, err); }); // 寫成一等公民函數的形式,要作的改動將會少得多: httpGet('/post/2', renderPost); // renderPost 將會在 httpGet 中調用,想要多少參數都行
// 純的 var checkAge = function(age) { var minimum = 21; return age >= minimum; }; //咱們也可讓 minimum 成爲一個不可變(immutable)對象,這樣就能保留純粹性,由於狀態不會有變化。要實現這個效果,必須得建立一個對象,而後調用 Object.freeze 方法: var immutableState = Object.freeze({ minimum: 21 });
// 柯里化 curry 的概念很簡單:只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數。 var add = function(x) { return function(y) { return x + y; }; }; var increment = add(1); var addTen = add(10); increment(2); // 3 addTen(2); // 12
// 咱們來建立一些 curry 函數享受下(譯者注:此處原文是「for our enjoyment」,語出自聖經) var curry = require('lodash').curry; var match = curry(function(what, str) { return str.match(what); }); var filter = curry(function(f, ary) { return ary.filter(f); }); match(/\s+/g, "hello world"); // [ ' ' ] match(/\s+/g)("hello world"); // [ ' ' ] var hasSpaces = match(/\s+/g); // function(x) { return x.match(/\s+/g) } filter(hasSpaces, ["tori_spelling", "tori amos"]); // ["tori amos"] var findSpaces = filter(hasSpaces); // function(xs) { return xs.filter(function(x) { return x.match(/\s+/g) }) } findSpaces(["tori_spelling", "tori amos"]); // ["tori amos"]
//代碼組合(compose,如下將稱之爲組合): var compose = function(f,g) { return function(x) { return f(g(x)); }; }; //讓代碼從右向左運行,而不是由內而外運行,我以爲能夠稱之爲「左傾」(籲——)。咱們來看一個順序很重要的例子: var head = function(x) { return x[0]; }; var reverse = reduce(function(acc, x){ return [x].concat(acc); }, []); var last = compose(head, reverse); last(['jumpkick', 'roundhouse', 'uppercut']); //=> 'uppercut' // 結合律(associativity) var associative = compose(f, compose(g, h)) == compose(compose(f, g), h); // true
//pointfree 模式指的是,永遠沒必要說出你的數據。咳咳對不起(譯者注:此處原文是「Pointfree style means never having to say your data」,源自 1970 年的電影 Love Story 裏的一句著名臺詞「Love means never having to say you're sorry」。) // 非 pointfree,由於提到了數據:word var snakeCase = function (word) { return word.toLowerCase().replace(/\s+/ig, '_'); }; // pointfree var snakeCase = compose(replace(/\s+/ig, '_'), toLowerCase);
TODO 未完待續 https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch6.htmljson