`

(转)Javascript的作用域,闭包的真真正含义

阅读更多
这文章写的真好:http://www.iteye.com/topic/1125744

javascript函数作用域分两个阶段
一个叫创建时阶段
一个叫运行时阶段

定义1:
所谓“创建时阶段”就是一个函数被以某种语法定义出来的时候,
并且此函数被创建在一个运行时阶段的作用域中时,此函数才为闭包状态,才能有自己的“创建时阶段”的作用域。

(在这里要说的是,所有被压入函数作用域链的值,都是对“可变对象”的引用,当所有这个“可变对象”的引用都断开的时候,这个“可变对象”才可能被垃圾回收,从内存中删去)

当浏览器的一个窗口被打开时,就自动开启了一个最顶级的"运行时阶段的作用域",
我们一般叫它“全局作用域”,所有在这个“全局作用域”中以某种语法定义出来
的函数就自动进入了“创建时阶段”,就有了自己“创建时阶段”的作用域。
并且自己“创建时阶段”的作用域链上自动插入,
创建自己的“运行时阶段”的“可变对象”的引用,
并且逐级插入。。。直道插入最后一个“可变对象”(就是最顶级的“运行时阶段”所产生的,一般我们叫它‘Global Object’).

定义2:
所谓“运行时阶段”就是一个函数被()操作符标识为要运行的时候,
此时,函数本身会创建一个内部对象,叫“运行期上下文”对象,
“运行期上下文对象”有自己的[[scope]]属性,此属性将copy此函数“创建时阶段”的[[scope]]属性的值,也就是“创建时阶段的作用域链”做为“运行时阶段的作用域链”的最初形态,有了这个最初形态以后,运行期上下文将组织聚集函数内部的所有标识符等等属性为一个对象,这个对象叫做"可变对象",然后将这个对象的引用压入自己作用域链的第一个位置。



下面做代码实例解析

Java代码  收藏代码

    var a = function() { 
     var i = 0; 
     var b = function() { 
       alert(i); 
     }; 
     return b; 
     
    } 



以上代码,此时a函数被以某种语法定义出来
a函数被创建在最顶级的“运行时阶段”的作用域链中,
此时a函数才被允许有自己的“创建时阶段”的作用域链。。。
此时a函数的作用域链上插入了创建自己的“运行时阶段”的“可变对象”的引用,
就是对"Global Object可变对象"的引用

此时b函数以某种语法定义出来,并且是被定义在a函数内部,
但由于a函数的作用域才处于“创建时阶段”
如果b函数要有自己的作用域就必须符合定义1
但很可惜不符合。。。因为b函数没有被创建在一个“运行时阶段”的作用域中,而是被创建在一个“创建时阶段”的作用域中,不满足定义1,所有b函数此时还没有作用域。

当执行以下这一行代码时
Java代码  收藏代码

    var b = a(); 



a函数被()操作符标识为要运行的时候,
此时,a函数本身会创建一个内部对象,叫“a函数运行期上下文-01”的对象,
(这里提示一下,每当a函数被运行的时候都会产生一个"a函数运行期上下文-XX"对象)
“a函数运行期上下文对象”有自己的[[scope]]属性,此属性将copy a函数“创建时阶段”的[[scope]]属性的值,也就是“创建时阶段的作用域链”做为“运行时阶段的作用域链”的最初形态,有了这个最初形态以后,运行期上下文将组织聚集函数内部的所有标识符等等属性为一个对象,这个对象叫做"可变对象",然后将这个对象的引用压入自己作用域链的第一个位置。

此时b函数终于符合定义1了,它被创建在一个“运行时阶段”的作用域链中,于是b函数有了自己的“创建时阶段”的作用域,并且“创建时阶段”的作用域链上插入a的可变对象的引用和全局可变对象的引用,此时a函数处于闭包状态。

当执行以下这两行代码时
Java代码  收藏代码

    var b = a(); 
    b(); 



当第一行代码执行完毕的时候,也就是当a函数执行完毕的时候,“a函数的运行期上下文对象”也被销毁,又此上下文创建的作用域链也销毁,所以对"a的可变对象"断开了引用,也就是说,如果“a的可变对象”如果没有其他引用的话随时会被垃圾回收释放内存,但是上面说了b函数处于闭包状态了,b函数的“创建时阶段”的作用域链已经有了一个对"a的可变对象"的引用,也就是说不会被垃圾回收无法释放内存,知道b函数执行完毕后“a的可变对象”和“b的可变对象”才都断开了引用,才会被垃圾回收释放内存。
分享到:
评论

相关推荐

    【JavaScript源代码】JS难点同步异步和作用域与闭包及原型和原型链详解.docx

     目录 JS三座大山同步异步同步异步区别作用域、闭包函数作用域链块作用域闭包闭包解决用var导致下标错误的问题投票机闭包两个面试题原型、原型链原型对象原型链完整原型链图 JS三座大山 同步异步同步异步区别...

    深入理解javascript原型和闭包

    深入理解javascript原型和闭包(01)——一切都是对象 深入理解javascript原型和闭包(02)——函数和对象的关系

    详解JavaScript作用域 闭包

    主要介绍了JavaScript作用域 闭包的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下

    JavaScript作用域、闭包、对象与原型链概念及用法实例总结

    本文实例讲述了JavaScript作用域、闭包、对象与原型链概念及用法。分享给大家供大家参考,具体如下: 1 JavaScript变量作用域 1.1 函数作用域 没有块作用域:即作用域不是以{}包围的,其作用域完成由函数来决定,...

    Web前端面试题目JavaScript(作用域,原型。原型链,闭包,封装函数).txt

    前端面试题,包含JavaScript的闭包,作用域,原型,原型链,上下文环境以及DOM,BOM封装函数深度克隆,以及一些常见的·JS问题,试题简单但是容易混淆,作为前端工程师必考题

    理解_JavaScript_闭包

    本文结合 ECMA 262 规范详解了闭包的内部工作机制,让 JavaScript 编程人员对闭包的理解从“嵌套的函数”深入到“标识符解析、执行环境和作用域链”等等 JavaScript 对象背后的运行机制当中,真正领会到闭包的实质。

    scope-chains-closures, Javascript作用域链和闭包 workshop.zip

    scope-chains-closures, Javascript作用域链和闭包 workshop 范围链和闭包 workshop正在启动$ npm install -g scope-chains-closures$ scope-chains-closures # or, shorter: sccjs使用箭头

    JavaScript使用闭包模仿块级作用域操作示例

    本文实例讲述了JavaScript使用闭包模仿块级作用域操作。分享给大家供大家参考,具体如下: 在阅读这篇文章之前,建议先阅读JavaScript的作用域链以及JavaScript闭包。 正如闭包的定义一样:“闭包指的是有权访问另一...

    作用域和闭包知识点文档

    JavaScript作用域与闭包知识点详细说明文档,有相关案例代码,欢迎下载,有问题可留言讨论哈哈哈!

    浅谈JavaScript作用域和闭包

    作用域和闭包在JavaScript里非常重要。但是在我最初学习JavaScript的时候,却很难理解。这篇文章会用一些例子帮你理解它们。 我们先从作用域开始。 作用域 JavaScript的作用域限定了你可以访问哪些变量。有两种作用...

    javascript作用域和闭包使用详解

    闭包与作用域链是 JavaScript 区别于其它语言的重要特性之一。 作用域JavaScript 中有两种作用域:函数作用域和全局作用域。 在一个函数中声明的变量以及该函数的参数享有同一个作用域,即函数作用域。一个简单的...

    深入理解javascript作用域和闭包

    作用域和作用域链是javascript中非常重要的特性,对于他们的理解直接关系到对于整个javascript体系的理解,而闭包又是对作用域的延伸,也是在实际开发中经常使用的一个特性,实际上,不仅仅是javascript,在很多语言...

    JavaScript闭包函数

    闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在...而闭包工作机制的实现很大程度上有赖于标识符(或者说对象属性)解析过程中作用域的角色。

    JavaScript中的作用域链和闭包

    JavaScript中出现了一个以前没学过的概念——闭包。何为闭包?从表面理解即封闭的包,与作用域有关。所以,说闭包以前先说说作用域

    你并不了解 JavaScript(YDKJS)第二版:作用域与闭包.epub

    你并不了解 JavaScript(YDKJS)第二版:作用域与闭包

    【JavaScript源代码】详解JavaScript闭包问题.docx

     一、变量的作用域 在介绍闭包之前,我们先理解JavaScript的变量作用域。变量的作用域分为两种:全局变量和局部变量。 var n = 999; //全局变量 function f1() { a = 100; //在这里a也是全局变量 alert(n); }...

    闭包作用域

    我自己总结的一点javascript闭包的作用域,可能不是太好

Global site tag (gtag.js) - Google Analytics