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

| #

| 引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值