- UID
- 8
- 精华
- 1
- 积分
- 2008
- 威望
- 14 点
- 宅币
- 1761 个
- 贡献
- 24 次
- 宅之契约
- 0 份
- 最后登录
- 2024-4-15
- 在线时间
- 279 小时
- QQ
用户组: 超级版主
- UID
- 8
- 精华
- 1
- 威望
- 14 点
- 宅币
- 1761 个
- 贡献
- 24 次
- 宅之契约
- 0 份
- 在线时间
- 279 小时
- 注册时间
- 2014-1-27
|
在这滥用概念的世界,到处都流传着一些谣言,是时候传播我自己的了。
JavaScript引擎当找到我们定义的函数时,会创建该函数的执行上下文(执行环境),并保存(压栈)作用域内的变量。当要调用函数时,将刚才保存的变量提供给函数使用(出栈),函数正常运行直到所有代码执行完。此刻,执行环境早已不复存在,JavaScript引擎会通知垃圾回收器回收“垃圾变量”。
闭包是阻止垃圾回收器将变量从内存中移除的方法,使得在创建变量的执行环境的外面能够访问到该变量。
这是书上的原话,个人以为这是不准确的说法。故事的主人公不应该是闭包,而是JavaScript引擎。有个关键的东西,叫做计数器,它是该函数执行环境的一个属性,从全局执行环境继承而来,默认为0。我可以猜到如果更改了默认值,JavaScript引擎不会启动垃圾回收器。可惜的是,我们不能直接访问该函数的执行环境。模块化在编程中很重要,用函数的方式实现了模块化。为了让模块重复使用不至于销毁,JavaScript语言有一种人为的间接方法,可以使得JavaScript引擎创建了一个闭包,更改了默认计数,阻止变量被清除。 这个方法不是书上指代的闭包,它与JavaScript语言有关系。
在JavaScript中,访问复杂的结构(数组、函数),都是引用该结构的地址。
JavaScript引擎一旦发现了引用,就会更改该函数的执行环境的计数器,需要再次使用的变量在内存中就被保留了下来,逻辑上确实是这样,书上也是这样教我的,但我不想就此止步。有引用就能间接地创建一个闭包吗?真的吗?我要做个实验,来证明作者是个混蛋,尽管他们有着十多年的架构经验。
- <script type = "text/javascript">
- // 例子1
- var b = 20;
- var my_func = function(){
- var a, c;
- a = 100;
- c = function(){
- return b; // 存在引用,但没有建立闭包。
- };
- c();
- }
- console.log( my_func() ); // 函数执行过程结束,变量my_func其值为undefined。
- </script>
- <script type = "text/javascript">
- // 例子2
- var b = 20;
- var my_func = function(){
- var a, c;
- a = 100;
- c = function(){
- return a; // 返回的是a,不是b,建立了闭包。
- };
- c();
- }
- console.log( my_func() ); // 函数执行过程结束,变量my_func其值为undefinded。
- </script>
复制代码
一旦返回的是内部变量,JavaScript引擎就会在原有的作用域里面插入一个创建好的闭包(保存着内部变量)。该函数运行时,之前的变量值由于在函数作用域内就可以再次被使用了。
综合上述:
JavaScript中的闭包(closure)不是指集合上的关系,而是函数作用域的一部分。 |
|