在看書遇到了講解js閉包的地方,講的太學術了 根本不明白 最近在網上搜集了些資料 發現了一些通俗易懂的講解 終於弄明白了閉包
要理解閉包,首先必須理解Javascript特殊的變量做用域。ide
變量的做用域無非就是兩種:全局變量和局部變量。函數
Javascript語言的特殊之處,就在於函數內部能夠直接讀取全局變量。this
Js代碼spa
var n=10;對象
function f1(){
alert(n);
}ip
f1(); //10內存
另外一方面,在函數外部天然沒法讀取函數內的局部變量(而經過閉包的形式就能夠實現)。作用域
Js代碼get
function f1(){
var n=999;
}
alert(n); // error
這裏有一個地方須要注意,函數內部聲明變量的時候,必定要使用var命令。若是不用的話,其實是聲明瞭一個全局變量!
Js代碼
function f1(){
n=10;
}
f1();
alert(n); // 10
但咱們有時候須要獲得函數內的局部變量,咱們怎麼得到呢?其實經過閉包的形式就能夠實現了。
在Javascript語言中,只有函數內部的子函數才能讀取局部變量,所以能夠把閉包簡單理解成「定義在一個函數內部的函數」。
因此,在本質上,閉包就是將函數內部和函數外部鏈接起來的一座橋樑
閉包能夠用在許多地方。它的最大用處有兩個,一個是前面提到的能夠讀取函數內部的變量,另外一個就是讓這些變量的值始終保持在內存中
如下是個js閉包的使用 其中內部函數getNum()就是個閉包函數, nAdd是個全局的匿名閉包函數
function getcounts(){
var n = 10;
nAdd = function(count){
n += count;
}
function getNum(){
alert(n);
}
return getNum;
}
var one = getcounts();
function gotoPage(){
one();
nAdd(2);
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
問題:有關js做用域鏈的問題
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //The Window
最近剛剛研究js閉包 小弟不明白爲何結果是The Window 而不是My Object
name不是全局變量麼? 外層的name不該該被object中的覆蓋麼?
答:
當在函數中訪問一個變量的時候,搜索順序是先搜索自身的活動對象(即return的function),若是存在則返回,若是不存在將繼續做用域鏈 上一個函數(即getNameFunc), 在return 的function做用域中是存在this.name的,即window.name,因此沒有必要再向上一個做用域去找。
function纔是做用域, object={}不是做用域。第一個做用域this就是有的啊,就是window對象,因此不用在找了。
this去掉以後在return function的做用域和getNameFunc的做用域中都找不到name了,只能到全局做用域中找到name = The Window。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return name;
};
}
};
alert(object.getNameFunc()()); //The Window
當你你試着寫成這樣時,由於如今return function的做用域,找不到再到和getNameFunc的做用域中找就找到了name=test var name = "The Window"; var object = { name: "My Object", getNameFunc: function () { var name = "test"; return function () { return name; }; } }; alert(object.getNameFunc()()); //test