js 点击闭包_学习Javascript闭包(Closure)
講的很清楚明了,連我都懂了,要是我們大學時的老師也能這么講課。。。他們只會放幻燈片
2009年8月30日 22:29
| #
| 引用
2009年8月30日 22:44
| #
| 引用
呵呵,可以作為面試題了!
2009年8月31日 09:30
| #
| 引用
十三
說:
閉包個人感覺是一種描述函數內部的數據結構,來描述函數的運行上下文.Javascript編程精粹 這本書算是講的比較好一點.
2009年8月31日 09:40
| #
| 引用
迷途小書童
說:
類是有行為的數據,閉包是有數據的行為。
2009年8月31日 10:26
| #
| 引用
tt
說:
阮兄:
有點疑問:
function f1(){
n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
可以寫成如下的不也一樣么?
function f1(){
n=999;
return n;
}
var result=f1();
alert(result);
2009年8月31日 21:16
| #
| 引用
@tt 實際上后種方法每次調用 f1 時,都會聲明 n = 999,而且 n 無法保留狀態值(嚴格按照你的代碼,其實 n 為全局變量,我理解你的本意為 var n = 999;)。
而第一種 f1 實際上返回的是個匿名函數,這樣 n 作用域被另外個 f2 函數作用域所使用,因此它會保留。n 不會被重復聲明,且內容會被保存
2009年9月 1日 13:20
| #
| 引用
這是我見過最簡單易懂的閉包教程。
支持下。
博主的博客寫的不錯,簡單易懂,東西涉及的很多方面我都有興趣,看來是同道中人,^_^
2009年9月 2日 16:49
| #
| 引用
一文中的!!!!!!!!!!!!
學習了!!
2009年9月 3日 11:08
| #
| 引用
想知道思考題的答案,
我以為是:My Object
2009年9月15日 00:09
| #
| 引用
steven
說:
頂樓主,我讀了一些文章。不是特明白。
有個問題。
記得有人說。外面的函數是closure,
好像樓主說里面的函數是closure.
不知道到底哪個是?謝謝。
2009年11月21日 14:51
| #
| 引用
jkd___w
說:
樓主講講最后一個思考題,沒明白
2009年11月26日 09:21
| #
| 引用
hou
說:
請版主講一講最后一個例子怎么回事,沒有看明白
2009年11月30日 16:00
| #
| 引用
George Wing
說:
函數中的this一般是指向window中的變量。
引用hou的發言: 請版主講一講最后一個例子怎么回事,沒有看明白
2009年12月13日 09:55
| #
| 引用
George Wing
說:
上面本人說得不太正確。
this的指向是由它所在函數調用的上下文決定的,而不是由它所在函數定義的上下文決定的。
2009年12月13日 10:23
| #
| 引用
George Wing
說:
如果非要指向object,可顯式的控制--把代碼的最后一句改為 alert(object.getName().call(object));
2009年12月13日 11:39
| #
| 引用
c-star
說:
阮大哥講的很透徹 受益匪淺
2009年12月18日 16:32
| #
| 引用
ya
說:
大道至簡,給予我這個初學者很大的幫助,謝謝!
2010年1月11日 09:30
| #
| 引用
過客
說:
淺顯易懂,很好。
如下看法,認為有待商榷:
#1、有一個地方需要注意,函數內部聲明變量的時候,一定要使用var命令。如果不用的話,你實際上聲明了一個全局變量!
#2、這段代碼中另一個值得注意的地方,就是“nAdd=function(){n+=1}”這一行,首先在nAdd前面沒有使用var關鍵字,因此nAdd是一個全局變量,而不是局部變量。其次,nAdd的值是一個匿名函數(anonymous function),而這個匿名函數本身也是一個閉包,所以nAdd相當于是一個setter,可以在函數外部對函數內部的局部變量進行操作。
function f1(){
test = 10;
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
//如果 #1 說法正確,下句會打印10,實際結果是test未定義。
//alert(test); // error test 未定義
//如果 #2 正確,語句 nAdd(); 位置在何處應該都能執行,測試結果在下面這個位置,也就是語句 var result=f1(); 前。是不能執行的。
//nAdd();
var result=f1();
result(); // 999
nAdd();
result(); // 1000
2010年1月28日 11:36
| #
| 引用
To 過客:
函數內部定義的方法和變量,要等到函數執行過以后,才會真正定義
2010年3月20日 16:17
| #
| 引用
但是從過客說的里面可以引出另外的問題,當使用這樣的代碼時。
function f1(){
test = 10;
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
如果在函數f1定義之前添加變量定義var n = 1;然后調用f1()();則顯示為999。說明nAdd中的n確實是作為全局變量存在。于是問題就來了——有什么方法讓他可以是父函數中定義的n呢?
2010年4月26日 15:28
| #
| 引用
大道至簡,很不錯!~ 這篇文章我要轉了...
2010年4月28日 22:48
| #
| 引用
引用George Wing的發言:
函數中的this一般是指向window中的變量。
this關鍵字代表的實例會根據環境不同而變化的. 他總是指向owner 看看這篇你大概就動this這個關鍵字了
2010年4月29日 12:34
| #
| 引用
tomwang
說:
最后一個題感覺和閉包沒什么關系啊,能詳細解釋一下嗎?因為當一個函數作為函數而不是方法來調用的時候,this指向的是全局對象,這在《Javascript權威指南》上說的很清楚,所以答案肯定是“The Window”,和閉包沒什么關系啊
2010年5月23日 18:24
| #
| 引用
最后一題重點在this
2010年8月25日 23:26
| #
| 引用
bao
說:
如果把f2申明成全局變量,道理一樣嗎?
2010年9月 6日 17:45
| #
| 引用
小貓
說:
太經典了!
終于理解了,一箭雙雕啊!既理解了this的用法,又理解了閉包
2010年9月16日 20:22
| #
| 引用
soberlevi
說:
這個例子很不錯,真的是一箭雙雕
2010年10月15日 09:29
| #
| 引用
小彘
說:
前面講得挺好的,淺顯易懂。對最后的兩個例子搞不清楚為啥。版主能不能具體分析下。
var obj=function()
{
var MyFunc=function()
{
alert("hello world");
}
return function()
{
return MyFunc;
}
}()
var f3=obj();
var f4=obj();
alert(f3 === f4);//為啥是TRUE;搞不懂
2010年10月24日 09:39
| #
| 引用
最后兩個例子很精煉 ^ ^
2010年11月11日 15:24
| #
| 引用
陳銳達
說:
嘗試解答代碼段一:
getNameFunc: function() {//假設函數名為A
return function()/*假設函數名為B*/ { return this.name; };
}
在函數里面構建函數的時候,閉包產生。
在函數B內調用函數A的this.name,由于函數A沒有name屬性,所以就去找全局變量name,找到了,所以返回“The Window”,要是沒有找到,則返回“undefined”。
代碼段二可以嘗試將代碼更改為:
var _this = this;
return function() { return _this.name +"__"+ this.name; };
2010年12月13日 15:50
| #
| 引用
LuckyGeb
說:
只有一點沒弄懂,如下代碼,nAdd在函數外為什么可以有意義?而test不行?想了好久,不知道那里有解答
function f1(){
test=10;
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
2011年1月17日 01:17
| #
| 引用
qdsang
說:
通俗易懂,, 閱覽無數教程, 看了這篇, 終于明白了點.
2011年1月24日 13:21
| #
| 引用
sf
說:
寫得太好了
2011年2月15日 16:47
| #
| 引用
這篇文章是阮兄一貫的風格,我喜歡,不過 "Javascript語言的特殊之處,就在于函數內部可以直接讀取全局變量。"這句有點奇怪,c不一樣可以在函數內部直接讀取全局變量么?難道不是么?
2011年3月 2日 22:02
| #
| 引用
ignition
說:
阮大哥能不能具體講下最后的思考題啊? 感覺關鍵在this
2011年3月 8日 15:56
| #
| 引用
三少爺
說:
變量的作用域無非就是兩種:全局變量和局部變量。
這句話值得商榷, 變量的作用域確實只有兩種, 不過他們是全局對象和函數.
你想說的或許是變量的類型有兩種?
2011年3月25日 20:15
| #
| 引用
軒脈刃
說:
理解最后兩個例子:
1 函數中的this指的是調用這個函數的owner
2 object.getNameFunc()是返回一個函數,并沒有執行函數中的代碼
3 增加一個例子0:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return (this.name);
}
};
var name = object.getNameFunc();
alert(name);
4 把例子1變成
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;//這個this是有上下文的限制的
};
}
};
var tmp = Object.getNameFunc(); //此時沒有執行this.name
var name = tmp();//這個時候才執行,這時候的this上下文為全局
alert(name);
//alert(object.getNameFunc()())
5 把例子2變成:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
var tmp = Object.getNameFunc();//這個時候執行了that = this,這里的this上下文是object,所以that指的是object
var name = Object.getNameFunc();//這個時候執行了that.name
alert(name);
//alert(object.getNameFunc()());
2011年4月19日 15:28
| #
| 引用
引用Jason的發言:
但是從過客說的里面可以引出另外的問題,當使用這樣的代碼時。
function f1(){
test = 10;
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
如果在函數f1定義之前添加變量定義var n = 1;然后調用f1()();則顯示為999。說明nAdd中的n確實是作為全局變量存在。于是問題就來了——有什么方法讓他可以是父函數中定義的n呢?
var n = 1;
function f1(){
var n = 999;
nAdd = function(){
n++;
}
function f2(){
alert(n);
}
return f2;
}
var b = f1();
nAdd();//n = 999+1 = 1000
b();//彈出 n 的值是 1000 (閉包內的變量n)
alert(n);//彈出n的值是 1 (全局)
全局的函數 nAdd 和 由f1返回的函數中 所使用到的變量n全部為f1函數內的局部變量n,而不是全局變量n,證據就是上面的代碼中最后一句 alert(n) 彈出的值是1, 也就是說 nAdd中的n++并沒有改變全局變量中n的值.
你自己描述的是 f1()() 顯示的是999,說明 n 是使用的f1內部的變量n,而非是全局變量n,不知道你為什么會有說明nAdd中的n確實是作為全局變量存在。這種想法呢? 如果想在nAdd中使用全局變量n(即在函數外面定義的n)的話,使用window.n來訪問.
2011年4月20日 14:56
| #
| 引用
樓主文章中的:二、如何從外部讀取局部變量?
這一整大段中的
n=999;
根據整篇文章所表達的內容,應該為:
var n=999;
因為如果沒有加var,則聲明的是全局變量,既然是全局變量,則在所有函數內部都是可見的,也就不會存在閉包這種說法.
請求樓主修正.
2011年4月20日 15:02
| #
| 引用
引用小彘的發言:
前面講得挺好的,淺顯易懂。對最后的兩個例子搞不清楚為啥。版主能不能具體分析下。
var obj=function()
{
var MyFunc=function()
{
alert("hello world");
}
return function()
{
return MyFunc;
}
}()
var f3=obj();
var f4=obj();
alert(f3 === f4);//為啥是TRUE;搞不懂
因為f3和f4都指向同一個地址(即MyFunc).var obj = (function() {
var MyFunc=function() {
alert("hello world");
}
return function() {
return MyFunc;
}
})();
var f3=obj();
var f4=obj();
alert(f3 === f4);//為啥是TRUE;搞不懂
2011年4月20日 15:05
| #
| 引用
小洪
說:
我測試了一下,為什么第一個例子輸出的什么都沒有是null,第二個我理解是myobject。誰能解釋下
2011年4月20日 16:48
| #
| 引用
Ruan YiFeng
說:
引用小秦的發言:
請求樓主修正.
謝謝指出,已更正。
2011年4月20日 16:53
| #
| 引用
起初以為函數內用var聲明變量,就等于用了this聲明,其實不是
var w=100;
function f1(){
//var w=101;
//this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:100
var w=100;
function f1(){
var w=101;
//this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:100
var w=100;
function f1(){
w=101;
//this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:101
var w=100;
function f1(){
//var w=101;
this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:102
看起來函數中的var和this并不是一個概念,函數內的局部變量與函數的屬性不是一回事,不過通過上面的情況能夠加深理解this和閉包
2011年4月22日 11:27
| #
| 引用
Aizen
說:
很不錯的講解,樓主寫的通俗易懂,很棒的理解,很受用!我的qq:290913917 希望有機會成為共同研究javascript和html5的伙伴,謝謝!
2011年5月 1日 00:10
| #
| 引用
lily
說:
我感覺第一個思考題是不是這樣理解:
首先this指向的是當前運行該函數的對象,
1、object.getNameFunc()得到了一個函數,函數為function(){return this.name}
2、object.getNameFunc()(),此時為window運行該函數,所以this指向的是window,所以this.name為The window
2011年5月 4日 11:29
| #
| 引用
foxracle
說:
做習題之前有一點需要很清楚:
內部函數可以訪問定義它們的外部函數的參數和變量(除了this和arguments之外)
如果需要訪問對象的name屬性的話,就需要顯示的定義一個變量that來引用this,而這個變量此時就指向object對象了。
第一題改成下面這樣就很清楚了。getNameFunc的第一個()是屬于方法調用,所以this綁定到了object對象,自然this.name為"My Object",但是閉包函數無法訪問這個this,它只能訪問到全局的this。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
alert(this.name);
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
2011年5月23日 15:44
| #
| 引用
CODER
說:
寫的真不錯。。。看了很多文章講閉包都是云里霧里的。。看了本文才恍然大悟。。。哦原來閉包如此簡單。。。。樓主寫的不錯。。。
2011年6月 2日 15:56
| #
| 引用
小超
說:
前面講的我都明白,但是最后兩個例子還是不明白,好多處都不懂!
1. var object = {。。。} 這是在干什么?是在聲明一個變量?還是在聲明一個類,然后里面有許多屬性?
2 . object.getNameFunc()(); 怎么會有兩個括號?
3. 如何判斷 this指向的是object 對象還是全局對象 ?
2011年6月14日 16:30
| #
| 引用
anoymous
說:
閉包是運行時中的概念,不能講哪個函數是一個閉包!而是哪個函數在運行時存在一個閉包!有時候,好幾個函數都可以組成一個閉包呢:
function ff()
{
var local=1;
this.add1=function()
{
return ++local;
};
this.add2=function()
{
return ++local;
}
}
var f=new ff();
alert(f.add1());//2
alert(f.add2());//3
2011年6月24日 14:33
| #
| 引用
Joe
說:
最后兩個例子中,第一個其實不是閉包,第二個是,但第二個例子其實不用那么復雜,直接把第一個例子中的this去掉就可以了。
2011年7月25日 14:02
| #
| 引用
Revo
說:
為什么第一個運行以后結果是result?!既不是window也不是object....???
2011年8月12日 15:31
| #
| 引用
eva
說:
function f1(){
n=999;
}
alert(n); // error
這段代碼在IE8和FIREFOX5上根本不能運行,求解釋...
2011年9月 2日 10:03
| #
| 引用
rush
說:
@eva
function f1(){
n=999;
}
alert(n); // error
很明顯啊,全局變量n是在函數f1中定義的,你不調用函數f1,n怎么定義呢
function f1(){
n=999;
}
f1();
alert(n);
這樣不就OK了
2011年9月 2日 11:27
| #
| 引用
At this time enhancements in could also be noticed in a point of contention.
2011年9月 8日 11:20
| #
| 引用
思考題中的例子貌似是 javascript高級程序設計里的。今天剛看到。
2011年9月28日 22:19
| #
| 引用
hyant
說:
你真是個有趣的人,為什么我總能在你這里找到我感興趣的博文?……
2011年10月11日 16:41
| #
| 引用
Legend1988
說:
樓主可以解釋一下思考題一嗎?我看很多人跟我一樣都不是很懂思考題一啊,萬分感謝!
2011年10月28日 10:13
| #
| 引用
huangyunbin
說:
引用Legend1988的發言:
樓主可以解釋一下思考題一嗎?我看很多人跟我一樣都不是很懂思考題一啊,萬分感謝!
同問,為什么this在嵌套函數中的意義不一樣
2011年11月 2日 16:37
| #
| 引用
apple
說:
this始終表示調用者的應用,第一個的閉包返回出來的一個函數,就是在window的環境下調用了這個函數,所以這個this是指向的window,而第二個把this保存在了that中。不知道說清楚沒有
2011年11月14日 18:03
| #
| 引用
Richard.Chou
說:
不錯,小伙子講的很到位,比一些書上生硬的翻譯要好一些。Good!
2011年11月16日 10:39
| #
| 引用
布田
說:
后面第1個例子怎么輸出result, result 是什么意思
2011年11月25日 10:19
| #
| 引用
noodles
說:
@陳銳達:
根據您的解釋,運行結果是不對的!如在A中定義name,執行結果一樣
2011年11月30日 23:24
| #
| 引用
追逐我的夢
說:
實際上,我認為閉包只是給外部函數提供了一個操作局部變量的途徑,局部變量本身并沒有改變,仍然為局部變量。
2011年12月 5日 23:04
| #
| 引用
艷陽天
說:
我也覺得最后兩個例子,好像跟this的關系更大……
2011年12月 9日 15:15
| #
| 引用
avatasia
說:
@tt 發問需謹慎, 文中的寫法是一種類的寫法, 域里有動作,你這個是函數。
2011年12月15日 10:45
| #
| 引用
清流魚
說:
漸漸地對閉包和this有點了解,尤其加上各位網友的激情討論,并附上示例,通俗易懂!
2011年12月22日 23:09
| #
| 引用
alex
說:
引用Joe的發言:
最后兩個例子中,第一個其實不是閉包,第二個是,但第二個例子其實不用那么復雜,直接把第一個例子中的this去掉就可以了。
不行哦,一定要引用一次,不然還不是閉包。
2012年2月10日 16:08
| #
| 引用
黃黃
說:
引用apple的發言:
this始終表示調用者的應用,第一個的閉包返回出來的一個函數,就是在window的環境下調用了這個函數,所以這個this是指向的window,而第二個把this保存在了that中。不知道說清楚沒有
我贊成。。
2012年2月28日 13:32
| #
| 引用
林子
說:
個人覺著樓主說的不是閉包
2012年3月12日 17:37
| #
| 引用
daniel
說:
初學者就這么理解閉包,最好不過了。
2012年4月 6日 15:28
| #
| 引用
思考題答案:The Window、My Object;其實最關鍵的就是要明白作用域鏈和閉包所起到的作用,其實閉包說到底就是一個函數,而且函數調用返回后其資源所占用的棧區并沒有釋放,,所以變量就還保存在內存中,由于作用域鏈的關系,它會去尋找離其最近的var聲明,var聲明所在就是該閉包所在的層,從而在這層里面所得到的結果就是它最后的值,于是乎返回值也就是這個最終的值了
2012年6月12日 14:13
| #
| 引用
袁huhu
說:
最后兩道思考題~ 其實和函數調用還有關系的~ 在以上例子中使用的是函數調用的方式,this這時候是指全局變量
2012年6月27日 10:51
| #
| 引用
紅雨
說:
引用afity的發言:
最后一題重點在this
正解,和閉包有什么關系啊
2012年7月10日 23:47
| #
| 引用
引用紅雨的發言:
正解,和閉包有什么關系啊
對于代碼片段一
object.getnameFunc() 返回的匿名閉包函數被全局變量所引用,其中的this指向
全局變量,當執行時打印The Window 。
對于代碼片段二
object.getnameFunc() 在返回閉包函數前,將this賦給that,此時getnameFunc是由
object調用的,故而this指向object,當內部函數被返回時,由于閉包的特性,仍然
能訪問到外部函數中的值,當執行打印My Object 。
2012年7月20日 19:37
| #
| 引用
徐相
說:
代碼段一、
當一個函數作為函數而不是方法調用的時候,這個this關鍵字引用全局對象。容易令人混淆的是,當一個嵌套的函數(作為函數)在一個包含的函數中調用,而這個包含的函數是作為方法調用的,這也是成立的:this關鍵字在包含的函數中有一個值,但是它卻(不太直觀地)引用嵌套的函數體的內部的全局對象。
所以第一個打印出來的是"The Window"
代碼段二、
由于this關鍵字不是在包含的函數中引用的,而是通過that=this這個調用的,所以這個this不是在閉包內的,因此這個this就不能調用函數體內的全局對象,而是他的局部對象object.name,所以第二個打印出來的是"My Object"
2012年8月 2日 10:33
| #
| 引用
編程大師
說:
說多無用,關鍵是理清函數什么時候作為對象使用,什么時候作為函數使用。
2012年8月18日 00:46
| #
| 引用
編程大師
說:
object.getnameFunc()() 也可以改為object.getnameFunc().call()
這就是javascript狡猾的地方。
2012年8月18日 00:49
| #
| 引用
講得很易懂 ··· 然后,最后思考題 感覺 是this關鍵字的問題,暫時還不懂··
2012年9月22日 20:11
| #
| 引用
請問阮兄/各位高人,假如某個JavaScript的函數對象已被調用過一次,如何用代碼驗證/判斷當該函數對象被第二次調用時,它是新創建的還是使用的內存中已有的?
2012年11月 3日 18:52
| #
| 引用
hanvslin
說:
引用tomwang的發言:
最后一個題感覺和閉包沒什么關系啊,能詳細解釋一下嗎?因為當一個函數作為函數而不是方法來調用的時候,this指向的是全局對象,這在《Javascript權威指南》上說的很清楚,所以答案肯定是“The Window”,和閉包沒什么關系啊
完全贊同這位仁兄的看法!!前面閉包講的不錯,但是最后面的思考題出的很爛啊,跟閉包沒關系,讓人看完了反而糊涂了!
2012年11月14日 14:21
| #
| 引用
有個特別大的疑問:
……原因就在于f1是f2的父函數,而f2被賦給了一個全局變量,……
f2真的被賦給一個全局變量了?
2012年12月10日 16:15
| #
| 引用
rst
說:
引用hanvslin的發言:
完全贊同這位仁兄的看法!!前面閉包講的不錯,但是最后面的思考題出的很爛啊,跟閉包沒關系,讓人看完了反而糊涂了!
最初我也以為思考題與文章主題無關,這兩天在反復看 JavaScript 權威指南 函數一章,都看暈了...
產生閉包效果的環境必須是嵌套函數的引用被保存到了一個全局作用域里面,也不難理解 阮老師思考題的設計了
2012年12月25日 17:21
| #
| 引用
在退出函數之前,將不使用的局部變量全部刪除。
請教一下這個改如何做?不太明白。。。Thanks!
2013年1月14日 13:35
| #
| 引用
初學JS
說:
保留內存值的解釋有點不好,即使var result = f1(); 即使這里不賦值給全局變量result,通過f1()();也不會改變n的值,呵呵~
2013年2月20日 17:29
| #
| 引用
后面的思考題 阮哥能解釋一下嗎
前面的例子是看懂了 但是思考題還是不會做
2013年2月20日 17:59
| #
| 引用
這里對于閉包的講解好一點:普通的函數內嵌,內部函數是先執行;而閉包則是:先把內部函數賦給外部函數,然后在執行。
2013年2月23日 12:11
| #
| 引用
跟阮老師學JS!
2013年2月27日 13:08
| #
| 引用
macrotea
說:
感覺應該從js作用域鏈及其原理來分析閉包,這樣才能徹頭徹尾明白!
2013年3月 2日 12:20
| #
| 引用
zhangyq
說:
引用George Wing的發言:
上面本人說得不太正確。
this的指向是由它所在函數調用的上下文決定的,而不是由它所在函數定義的上下文決定的。
這里說的this才是正確的。如果將此處的this能夠輕松的理解,我想本文的最后一道題就懂了。你怎樣認為呢?
2013年3月 6日 10:51
| #
| 引用
douya0808
說:
每個函數在被調用時,其活動對象都會自動取得兩個特殊變量:this和arguments。內部函數在搜索這個變量時,只會搜索到其活動對象為止,因此永遠不可能直接訪問外部函數中的這兩個變量(這一點通過前面的圖可以看得更清楚)。意思就是說找到匿名函數中的this和arguments就不會再往下找了(這里的往下指的是外層的包含函數,和最外層的window全局環境),而匿名函數的this對象通常指向window,所以輸出的是全局的那個字符串。不過,把外部作用域中的this對象保存在一個閉包能夠訪問到的變量里,就可以讓閉包訪問該對象了
2013年4月 9日 19:57
| #
| 引用
不執行調用f1肯定不可能生成test變量,第二個問題同樣的原因。引用過客的發言:
淺顯易懂,很好。
如下看法,認為有待商榷:
#1、有一個地方需要注意,函數內部聲明變量的時候,一定要使用var命令。如果不用的話,你實際上聲明了一個全局變量!
#2、這段代碼中另一個值得注意的地方,就是“nAdd=function(){n+=1}”這一行,首先在nAdd前面沒有使用var關鍵字,因此nAdd是一個全局變量,而不是局部變量。其次,nAdd的值是一個匿名函數(anonymous function),而這個匿名函數本身也是一個閉包,所以nAdd相當于是一個setter,可以在函數外部對函數內部的局部變量進行操作。
function f1(){
test = 10;
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
//如果 #1 說法正確,下句會打印10,實際結果是test未定義。
//alert(test);// error test 未定義
//如果 #2 正確,語句 nAdd(); 位置在何處應該都能執行,測試結果在下面這個位置,也就是語句 var result=f1(); 前。是不能執行的。
//nAdd();
var result=f1();
result(); // 999
nAdd();
result(); // 1000
2013年4月30日 18:50
| #
| 引用
Black
說:
引用George Wing的發言:
上面本人說得不太正確。
this的指向是由它所在函數調用的上下文決定的,而不是由它所在函數定義的上下文決定的。
哦。看了你這個解釋就了解了
2013年5月28日 15:38
| #
| 引用
curran
說:
說的很易懂,最后兩個例子還是有點模糊
2013年5月30日 11:37
| #
| 引用
為什么話要反著說呢,應該說正例,這著用太糟糕了,贊同 @迷途小書童 @steven
2013年6月 8日 15:11
| #
| 引用
范小龍
說:
引用tomwang的發言:
最后一個題感覺和閉包沒什么關系啊,能詳細解釋一下嗎?因為當一個函數作為函數而不是方法來調用的時候,this指向的是全局對象,這在《Javascript權威指南》上說的很清楚,所以答案肯定是“The Window”,和閉包沒什么關系啊
《Javascript權威指南》上說:如果嵌套函數作為函數調用,其this值不是全局對象(非嚴格模式下)就是undefined(嚴格模式下);
如果嵌套函數作為方法調用,其this值指向調用它的對象。所以代碼片段一,getNameFunc()作為object的方法,所以this值應該指向調用它的對象(object),而object自己定義name為"My Object",所以片段一,我覺得應該是彈出"My Object"。我是新手,我只是從this方向對這個函數分析,有錯誤的地方,還望高手指點。
2013年6月18日 15:50
| #
| 引用
“閉包的概念”這一節總結的非常好,淺顯易懂。同時,也了解了閉包的兩個用處:一個是可以讀取函數內部的變量,另一個就是讓這些變量的值始終保持在內存中。
2013年6月27日 20:59
| #
| 引用
zz
說:
最后兩個例子關鍵是區分object.getnameFunc()調用時和調用后的this指向。
第一個問題,object.getnameFunc()()函數在執行時this屬于全局域,因此結果是the window
第二個問題,通過使用that=this 保留了在調用object.getnameFunc()時的this狀態值。因此在getnameFunc()的閉包中訪問的變量是已經不是this的了,而是that的~
2013年7月25日 21:06
| #
| 引用
陳默
說:
JS新手,學習了,思考題和討論很強大。
2013年7月30日 14:34
| #
| 引用
張雨閣
說:
思考題解答(個人見解):
1、因為閉包最后的返回值是一個函數,注意緊緊是一個函數而已 并沒有執行,等到alert調用時才執行,而這時執行調用的方法,前面阮老師說了,函數內沒有var聲明的事全局變量,所以調用的getName是一個全局的變量,所以對應this找到的是全局的name.
2、因為this的對象引用在編譯時就已經確定了,就是object,所以返回值在Object中開始查找,找到了Obeject中的name就不到全局變量中查找。
2013年8月19日 11:23
| #
| 引用
abel533
說:
綜合各種理解之后,我明白最后的“代碼片段一”中的閉包函數中的this是window對象,也就是說..閉包函數的范圍竟然是window。。。
2013年8月22日 16:43
| #
| 引用
superx
說:
這么理解還不如不理解,這樣下來對新手是一種誤導。所以說才建議大家盡量都去看英文網站。唉
2013年9月24日 09:37
| #
| 引用
wei
說:
其實看完這篇文章,對于閉包的概念就有了更深刻的理解
最后留的兩道題目,很好的說明了這一點。
因為第一題中getNameFunc這個方法或者叫函數是屬于全局作用域的,所以里面返回的this始終都是指向window的。而第二題中用that=this改變了當前函數指向的作用域,所以第二題中的this最終只想的是myobject。
不知道我的理解正確不正確。
如果說錯,請勿見怪...
2013年10月 9日 23:37
| #
| 引用
nebula
說:
return function() {
return this.name;
}
這里的this代表調用方法時所在的的作用域:全局作用域window。
return function() {
return that.name;
}
object.getNameFunc()()此處實現了從外部調用局部變量的方法,that會順著作用域鏈向上級作用域查找,所以獲得是getnameFunc的定義的變量var that = this。
2013年11月13日 15:23
| #
| 引用
@小彘:
是引用類型。f3和f4的值是指針,只想obj()。所以全等是true。
2013年11月13日 18:47
| #
| 引用
后兩個應該this的作用域問題,不是閉包的問題吧。 弄的我都糊涂了... 還好找了一篇通俗的問題在,終于弄懂了
2013年12月 3日 10:31
| #
| 引用
小小技術員
說:
執行過f1這個函數后,test如果是局部變量會被銷毀,如果是全局變量則會保存在內存堆(heap)里,如果不執行f1函數,test和nadd都是不存在的
2013年12月 5日 13:53
| #
| 引用
小小技術員
說:
不,我補充一下,我應該是說錯了,既然f2函數是閉包,那么f2函數會保持它的外部函數f1的作用域,即使定義test為f1函數的局部變量(var test = 10);那么也要先檢查f2是否對test產生引用,如果引用數為0,則在f1()調用完后銷毀,再運行f1()()(實際上是調用f2函數)也不會產生對test這個局部變量的引用,所以它就在棧中被銷毀了。
如果理解的不對,請大俠們拍磚
2013年12月 5日 14:19
| #
| 引用
_____LG
說:
最后的思考題如果能理解這句話“this的指向是由它所在函數調用的上下文決定的,而不是由它所在函數定義的上下文決定的”,我想就能它們的運行結果了
2014年1月 6日 16:29
| #
| 引用
this的指向是由它所在函數調用的上下文決定的,而不是由它所在函數定義的上下文決定的。喜歡這句話,但是閉包還是沒有理解透徹。
2014年1月14日 15:14
| #
| 引用
陳守川
說:
我覺得大家說了這么多,都沒人把代碼寫出來運行一下來驗證自己的答案么,也不管自己的答案是否正確么。通過運行發現:
思考題一:打印:空白
思考題二:打印:My Object
雖然我不太了解,但是評論中的很多人自己也理解錯誤了。
2014年2月17日 11:56
| #
| 引用
jprovim
說:
R兄講的非常簡單易懂。
2014年2月22日 06:25
| #
| 引用
bryantzhang
說:
我覺得是這樣的,
第一個里邊的this指向的是那個閉包函數,
第二個例子里邊的this指向的是object。
引用陳守川的發言:
我覺得大家說了這么多,都沒人把代碼寫出來運行一下來驗證自己的答案么,也不管自己的答案是否正確么。通過運行發現:
思考題一:打印:空白
思考題二:打印:My Object
雖然我不太了解,但是評論中的很多人自己也理解錯誤了。
2014年2月25日 10:59
| #
| 引用
陳輝
說:
第一個 打印結果為 The window
第二個 打印結果為 My Object
第一個 this為全局對象,所以alert處理的name為The window
第二個 that 為object對象,所以alert 處理的name為My object
第二個好理解,因為在調用前用that 保存了object 自己的this,所以that 就成為是有變量,在閉包內可以調用。
第一個有點暈,因為第一個的this指向自己,然后被window 給調用this 就成了window對象,它的name就是全局的name引用陳守川的發言:
我覺得大家說了這么多,都沒人把代碼寫出來運行一下來驗證自己的答案么,也不管自己的答案是否正確么。通過運行發現:
思考題一:打印:空白
思考題二:打印:My Object
雖然我不太了解,但是評論中的很多人自己也理解錯誤了。
2014年3月16日 15:49
| #
| 引用
這篇文章流傳很廣,看了多次,忍不住要問了。下面這句話:
---------
Javascript語言的特殊之處,就在于函數內部可以直接讀取全局變量。
-----------
請問有哪種語言是“不”可以在函數內部直接讀取全局變量的? 全局變量什么意思,就是在任何地方都可以讀取。
2014年3月29日 23:27
| #
| 引用
Ming
說:
引用忍不住要問了的發言:
請問有哪種語言是“不”可以在函數內部直接讀取全局變量的? 全局變量什么意思,就是在任何地方都可以讀取。
我覺得這句話可以改成:
Javascript語言的特殊之處,就在于函數內部可以直接聲明(不使用var)并讀取全局變量。
2014年4月23日 01:44
| #
| 引用
Asakura
說:
引用忍不住要問了的發言:
這篇文章流傳很廣,看了多次,忍不住要問了。下面這句話:
---------
Javascript語言的特殊之處,就在于函數內部可以直接讀取全局變量。
-----------
請問有哪種語言是“不”可以在函數內部直接讀取全局變量的? 全局變量什么意思,就是在任何地方都可以讀取。
同感啊,一直對此很費解
2014年5月11日 15:34
| #
| 引用
yuanboss
說:
感覺基本是參考《javascript高級程序設計》這本書里面的
2014年5月15日 22:12
| #
| 引用
阮一峰
說:
本文關閉,不再接受回復。
2014年5月27日 20:42
| #
| 引用
總結
以上是生活随笔為你收集整理的js 点击闭包_学习Javascript闭包(Closure)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stotybord如何添加子视图_SQL
- 下一篇: drbd实现mysql地热备_Mysql