閉包,函數式編程學習小記

對象是包含行爲的數據,閉包是包含數據的行爲。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

相關文章
相關標籤/搜索