江湖上都說要了解閉包,得先了解做用域鏈,因此,先從做用域鏈開始吧。javascript
咱們來看一個栗子html
var word = " the window" function sayWord(){ var word = "sayWord" function sayHello(){ var word = "sayHello" alert(word) } return sayHello } sayWord()();
上例的做用域鏈就是:
sayHello[word="sayHello"]
——sayWord[word="sayWord"]
——window[word="the window"];
當執行sayHello函數時,會沿着這個做用域鏈一級一級往上找word這個變量,直到找到爲止。前端
javacript高級程序設計上說「有很多開發人員老是搞不清匿名函數和閉包這兩個概念」。很遺憾,本人就是。java
閉包是指有權訪問另外一個函數做用域中的變量的函數。github
@xiaotie閉包
閉包是從用戶角度考慮的一種設計概念,它基於對上下文的分析,把齷齪的事情、複雜的事情和外部環境交互的事情都本身作了,留給用戶一個很天然的接口。函數
@javacript權威指南this
函數對象經過做用域鏈相互關聯起來,函數體內部的變量均可以保存在函數做用域內設計
上栗子
var word = " the window" function sayWord(){ var word = "sayWord" function sayHello(){ alert(word) } return sayHello } sayWord()();
sayHello函數在sayWord函數內部,它能訪問sayWord函數內部的變量。sayHello函數就是閉包,
function createCounter() { var counter = 0; function increment() { counter = counter + 1; console.log("Number of events: " + counter); } return increment; } var counter1 = createCounter(); var counter2 = createCounter(); counter1(); // Number of events: 1 counter1(); // Number of events: 2 counter2(); // Number of events: 1 counter1(); // Number of events: 3
每次調用函數都會建立變量綁定對象添加到做用域鏈中,因此每次調用外部函數的時候,做用域鏈都是不一樣的。而對於嵌套函數,每次調用外部函數時,內部函數又會從新定義一遍。
this對象的指向問題
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var name = "The v"; return function(){ return this.name; }; } }; alert(object.getNameFunc()()); //"The Window"(在非嚴格模式下)
每一個函數在被調用時都會自動取得兩個特殊變量:this
和arguments
。內部函數在搜索這兩個變量時,只會搜索到其活動對象爲止,所以永遠不可能直接訪問外部函數中的這兩個變量。
這裏
object.getNameFunc()()==(function(){return this.name;})()
因此其活動對象爲window;
解決辦法
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()()); //"My Object"
內存泄露問題
function sayWord(){ var word = "hello" add = function(){ word = word + " world" } function sayHello(){ alert(word) } return sayHello; word = null; } var say = sayWord(); say(); //hello add(); say(); //hello world
注意:由於閉包的這個特性,因此外部函數的變量是其內部全部閉包的共享值,所以,不能在閉包中隨意的改變外部函數的變量值,牽一髮而動全身。
若是以爲本文不錯的話,幫忙點擊下面的推薦哦
>>>>點擊閱讀原文