直接上代码代码简单
function Foo(){
var i=0;
return function(){
document.write(i++);
}
}
var f1=Foo(),
f2=Foo();
f1();
f1();
f2();
问题,被引入到外部作用域是如果保存的,答案是010,f1和f2如何实现的隔离,如果有图的话就更好了;我觉得大部分网上关于闭包都讲得太抽象,不够具体和直接
i这个变量到底保存在哪个作用域,f2、f1不指向一个函数作用域么
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
你可以把 f1 = Foo()当作一个变量赋值;
所以 f2 和 f1 中的i 互不影响,因为都在各自新的作用域内。
留意Foo的定义,里面用var定义了一个闭包内的变量i,每执行一次Foo就初始化一个新的i,这就是f1和f2的里的i分别独立的原因。
但对于f1来说,f1每次执行都是指向同一个i,就是f1 =Foo()这一句初始化的i,每次执行都给它加1。
这么跟你说吧:在为
f1和f2赋值的时候调用Foo()会将i重新设为0。而运行f1和f2的时候只是在运行闭包,跟var i = 0;没有关系了。F1和F2中的i都是放在单独的作用域中,互不影响的人
我自己的理解,仅作参考。
函数定义有三种方式:其中一种就是字面量方式。
var f1 = function(){}你的Foo()返回的返回值是一个匿名函数,如果从函数定义的角度来说
var f1 = Foo()等价于var f1 = function(){document.write(i++)}var f2 = Foo()等价于var f2 = function(){document.write(i++)}然后根据闭包,作用域链的相关知识。(楼上的朋友已经有回答)
f1(),第一次执行后0。
f1(),第二次执行后1。
f2(),第一次执行后0。
这只是我自己的拙见,仅供参考。
两次执行Foo,虽然都是返回 funtion(){} 但是两次返回的其实不是同一个function 你只要执行一下 f1==f2 就知道了,既然返回的是两个不同的function 那么 他们对应的scope肯定也是不同的。
f1和f2引用的是两个执行环境
你要的图来了!
1. 刚定义完函数
Foo时:2. 所有代码执行完时:
3. 说明一下:
问题的关键时:
(1) 函数在执行期间会产生一个执行上下文(EC),作为函数的运行时表示,函数返回时此上下文销毁。所以很函数
Foo被调用了两次必然产生两个不同的执行上下文。(2) 执行上下文中有个叫做词法环境(LE)的东西,用来存放函数执行时产生的局部变量、this等东西。函数
Foo里面的局部变量i就放在词法环境LE里面。(3) 函数返回后,执行上下文销毁了,但是词法环境还是可以存在的,所以你要问
i存放在哪里?不错,就在词法环境里面。(4) 函数里面定义的内部函数总是有一个内部指针(即图中的[[scope]])指向外部词法环境。所以f1和f2可以引用它们的外部词法环境中的各自的
i变量,并对它们进行操作。如果还有什么不明白的,可以留言。
注:为了方便理解,图中某些地方进行了简化,但是本质没有变化。
Foo 每次执行时会产生一个新的scope, f1和f2分别绑定到两个这样的scope, 里面各有一个同名变量i
楼主,这个貌似不太好用图来说明,这里每次调用Foo()函数时,都会执行一次var i=0; 而 f1 和 f2 是分两次调用的,所以会生成两个完全独立的 i 变量,尽管名字相同,但是却是生存在两个不同的作用域中的变量,执行 f1 函数不会影响 f2 函数中的 i 的值,反之执行 f2 同样也不会影响 f1中 i 的值,f1 和 f2 只和各自的 i 变量保持着联系。不知这样会不会好理解一点
ps: 这是另一个类似问题中用户 bachelor 的回复,我觉得解释的还比较明朗:
楼上的各位都在关注闭包,其实题主更应该关注的是这个变量i,因为你每执行这个函数,变量i就重新初始化。
正应为重新执行函数以后,才得到的楼主的答案。
继续回到题主的问题上,如果想让i不被重新执行函数的时候初始化,该怎么办?很简单。
将变量i变成相对于函数外全局变量,也就是如下这样:
var i = 0;
function Foo() {
}
var f1 = Foo(),
f1(); // 0
f1(); // 1
f2(); // 2
2 不用var声明,不过这样是不推荐的,容易造成变量混乱。