作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域。 闭包一般发生在嵌套作用域中。闭包是JavaScript最强大的特性之一,很多高级应用都要依靠闭包实现。如OO的私有成员和模块化等。然而闭包虽然强大,但一般比较占用内存另外如果使用不当还会引起内存泄露,对闭包有了解的jser一般都知道闭包的这些个问题,本文先阐述了闭包和作用域链的关系,然后分析了产生这些个问题的原因。下面是一段闭包的示例代码:

var  name = "windows's name";
var object = {
    name : "object's name",
    getNameFunc:function(){
        var that = this;
        return function(){
            return that.name;
        }
    }
};
console.log(object.getNameFunc()());

    当javascript代码执行时会创建一个执行上下文对象,执行上下文对象包含一个作用域链,作用域链有一个或多个变量对象组成,作用域链中保存的是对变量对象的引用。变量对象定义了在当前作用域中声明的变量和函数。在代码的执行过程中JAVASCRIPT引擎会按照自上而下的顺序检索作用链中的变量对象的成员来解析需要被访问(读或写)的变量或函数,在检索过程中如果在作用域链的某个变量对中象查找到与之匹配的标识符就会终止检索。通过这种方式当在代码中如果有同名的变量就可以区分出来我们要操作那个变量。
    当代码载入完成后 Javascript引擎会创建一个全局的执行上下文,全局执行上下文的作用域链只包含一个全局变量对象。Javascript的函数对象拥有一个私有的socpe属性,当函数被创建时会使用当前的作用域链初始化函数scope属性。当函数被执行时会创建函数的执行上下文对象和当前作用域的变量对象,创建函数的执行上下文对象时先使用函数的scope属性给执行上下文对象的作用域链赋值,再把创建的变量对象放入作用域链的顶端来初始化执行上下文的作用域链。位于作用域链顶端的变量对象也称为活动对象。默认情况下当函数返回时会销毁它的活动对象和作用域链,这也是为什么我们函数的外部不能够访问到在函数内部定义的成员。然而在发生闭包的情况下,当内部函数被创建时,内部函数的scope属性指向包含它的外部函数的作用域链。这时内部函数引用了外部函数的活动对象,当外部函数返回时,它的活动对象没有被释放,直到引用它的内部函数被销毁时才会释放外层函数的活动对象。所以它所包含的内部函数仍然可以访问在外部函数中定义的成员,另外这也是闭包比较占用内存的原因。
    内存泄露问题是由于部分浏览器使用引用计数来作为垃圾回收机制,当在我们的代码中发生了循环引用时,就会造成资源不能被回收从而引起内存泄露。发生内存泄露有时是因为在我们的代码中发生了明显的循环引用,有时则不那么明显。对于前者一般通过仔细检查代码就能发现问题所在,对于后者就需要我们对闭包有足够的了解才能发现。如下面代码:

function outerFunc(){
    var obj = document.getElementById("element");
    obj.onclick=function innerFunc(){
        alert("Hi! I will leak");
    };
    obj.bigString=new Array(1000).join(new Array(3000).join("XXXXX"));
    // This is used to make the leak significant
};

    在上面这段代码中,外部函数outerFunc中的局部变量obj引用文档中ID为element的Dom元素,obj.onclick指向内部函数innerFunc的引用,内部函数innerFunc的scope属性指向的作用链中包含外部函数outerFunc的活动对象的引用,活动对象的obj成员再次指向文档中ID为element的Dom元素从而构成了循环引用。

Javascript中闭包的作用域链的更多相关文章

  1. javascript中闭包与作用域的理解

    很多js的框架与插件编写都用到了闭包,所以,阅读和掌握闭包很有必要.最近学习vue框架时,经常会猜想很多功能的native js实现,很多都应用到了闭包,闭包除了目前已知的一些特性,如:可以保持局部变 ...

  2. javascript 执行环境,作用域链和闭包

    首先看下这条语句: (function($) {…})(jQuery): 1.原理: function(arg){…}这就定义了一个匿名函数,参数为arg 而调用函数时,是在函数后面写上括号和实参的, ...

  3. 浅谈JavaScript中闭包

    引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...

  4. [ JS 进阶 ] 闭包,作用域链,垃圾回收,内存泄露

    原网址:https://segmentfault.com/a/1190000002778015 1. 什么是闭包? 来看一些关于闭包的定义: 闭包是指有权访问另一个函数作用域中变量的函数 --< ...

  5. JS闭包、作用域链、垃圾回收、内存泄露相关知识小结

    补充: 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变 ...

  6. 在JavaScript中闭包的作用和简单的用法

    在JavaScript中闭包的作用和简单的用法 一.闭包的简介 作用域链:在js中只有函数有作用域的概念,由于函数内能访问函数外部的数据,而函数外部不能访问函数内部的数据,由上述形成一种作用域访问的链 ...

  7. 在Javascript中闭包(Closure)

    在Javascript中闭包(Closure) 什么是闭包 “官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. ...

  8. javascript中闭包最简单的简绍

    javascript中闭包是什么 JavaScript 变量可以是局部变量或全局变量.私有变量可以用到闭包.闭包就是将函数内部和函数外部连接起来的一座桥梁. 函数的闭包使用场景:比如我们想要一个函数来 ...

  9. javascript中的this作用域详解

    javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...

随机推荐

  1. ios获取权限

    ios获取权限 by 伍雪颖 -(void)requestRecord{ [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL ...

  2. [转]laravel 4之视图及Responses

    http://dingjiannan.com/2013/laravel-responses/   laravel 4之视图及Responses 16 Aug 2013 Laravel的Response ...

  3. C++中malloc/free和new/delete 的使用

    malloc/free 的使用要点 函数malloc的原型如下: void * malloc(size_t size); 用malloc申请一块长度为length的整数类型的内存,程序如下: int ...

  4. Spring项目的建立-移植流程(非入门教程)

    Creat by Zhou yong in 2016/4/15/19:00 jar包 java 1.7 tomcat的两个jar包 2个文件上传的jar包 json支持的jar包 hibernate- ...

  5. 21. DNS 配置和端口检测

    一.将本机的 DNS 配置为 8.8.8.8 ,用 nslookup (还可以使用 host.dig)验证 # 修改配置文件     # vim /etc/resolv.conf # 在文件的最后加入 ...

  6. OMXCodec与OMX事件处理流程

    学习了解Mutilmedia Framework有一段时间了,今天闲下来稍微整理整理.OMXCodec.cpp类属于libstagefright,在整个MM PF 相当OMX的适配层,供awesome ...

  7. javascript的本地存储 cookies、localStorage

    一.cookies 本地存储 首先是常用的cookies方法,网上有很多相关的代码以及w3cSchool cookies. // 存储cookies function setCookie(name,v ...

  8. XtraReport改变纸张方向

    XtraReport纸张方向改变可以通过修改Landscape属性: Landscape=true 为横向输出 Landscape=false 为纵向输出

  9. iOS 发布证书错误 Your build settings specify a provisioning profile with the UUID, no provisioning profile was found

    解决办法 1.找到项目中的**.xcodeproj文件,点击右键,show package contents(打开包内容). 2.打开后找到project.pbxproj文件,用文本编辑器打开.其实就 ...

  10. (转) Overloads and templates

    Overloaded functions In C++, two different functions can have the same name if their parameters are ...