Javascript中闭包的作用域链
作用域定义了在当前上下文中能够被访问到的成员,在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中闭包的作用域链的更多相关文章
- javascript中闭包与作用域的理解
很多js的框架与插件编写都用到了闭包,所以,阅读和掌握闭包很有必要.最近学习vue框架时,经常会猜想很多功能的native js实现,很多都应用到了闭包,闭包除了目前已知的一些特性,如:可以保持局部变 ...
- javascript 执行环境,作用域链和闭包
首先看下这条语句: (function($) {…})(jQuery): 1.原理: function(arg){…}这就定义了一个匿名函数,参数为arg 而调用函数时,是在函数后面写上括号和实参的, ...
- 浅谈JavaScript中闭包
引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...
- [ JS 进阶 ] 闭包,作用域链,垃圾回收,内存泄露
原网址:https://segmentfault.com/a/1190000002778015 1. 什么是闭包? 来看一些关于闭包的定义: 闭包是指有权访问另一个函数作用域中变量的函数 --< ...
- JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
补充: 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变 ...
- 在JavaScript中闭包的作用和简单的用法
在JavaScript中闭包的作用和简单的用法 一.闭包的简介 作用域链:在js中只有函数有作用域的概念,由于函数内能访问函数外部的数据,而函数外部不能访问函数内部的数据,由上述形成一种作用域访问的链 ...
- 在Javascript中闭包(Closure)
在Javascript中闭包(Closure) 什么是闭包 “官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. ...
- javascript中闭包最简单的简绍
javascript中闭包是什么 JavaScript 变量可以是局部变量或全局变量.私有变量可以用到闭包.闭包就是将函数内部和函数外部连接起来的一座桥梁. 函数的闭包使用场景:比如我们想要一个函数来 ...
- javascript中的this作用域详解
javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...
随机推荐
- Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8526644 在Android系统中,输入法窗口 ...
- linux服务器时间同步
date命令: date :查看当前时间,结果如下:Tue Mar 4 01:36:45 CST 2014 date -s 09:38:40 :设置当前时间,结果如下:Tue Mar 4 09:38: ...
- Docker网络管理-外部访问容器
注意:这里使用的方法是端口映射,需要说明的是端口映射是在容器启动的时候才能完成端口映射的. 1,搭建1个web服务器,让外部机器访问. docker run -itd centos /bin/bash ...
- SQLServer 跨服务器查询的两个办法
网上搜了跨服务器查询的办法,大概就是Linked Server(预存连接方式并保证连接能力)和OpenDataSource(写在语句中,可移植性强).根据使用函数的不同,性能差别显而易见...虽然很简 ...
- JQuery 之事件中的 ----- hover 与 onmouseover 、onmouseout 联系
hover([over,]out) 一个模仿悬停事件(鼠标移动到一个对象上面及移出这个对象)的方法.这是一个自定义的方法,它为频繁使用的任务提供了一种“保持在其中”的状态. 当鼠标移动到一个匹配的元素 ...
- php的一些特殊用法
php ruturn的另一个用法 database.php <?php return array ( 'hostname' => 'localhost', 'database' => ...
- java加载资源文件
className.class.getResourceAsStream 用法: 第一: 要加载的文件和.class文件在同一目录下,例如:com.x.y 下有类Test.class ,同时有资源文件c ...
- GDI 开发的准备工作
1 需要的链接库和头文件 大部分函数在 Gdi.dll 和 Gdi32.dll 提供.相关的函数接口和结构都在 Wingdi.h 文件中(如果工程中已包含 Windows.h 就不需要再包含了,因为 ...
- php 技巧、高效率写法 推荐(转载+总结)
0.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的"函数" ...
- mysql 复习与学习(二)数据库及表结构的创建删除
mysql -h localhost -uroot -p123456 //连接数据库 show databases; //查看数据库 create database if not exists db_ ...