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中却经常让我觉 ...
随机推荐
- 动态修改UINavigationBar的背景色
这是我们最终想要得到的效果: 思路 在UISrollView的delegate方法 1 - (void)scrollViewDidScroll:(UIScrollView *)scrollView ...
- jQuery 事件 - error() 方法
实例 如果图像不存在,则用一段预定义的文本取代它: $("img").error(function(){ $("img").replaceWith(" ...
- JS 根据Url参数名称来获取对应的值 方法封装
function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&] ...
- iOS 之 cocoapods安装与使用
我们都知道第三方库,一般使用cocoapods管理,cocoapods在我们IOS开发中有着很大的作用. 好了,现在看下它的安装步骤: 1.打开终端,输入 sudo gem install cocoa ...
- javascript父窗口与子窗口通信
在父窗口的js代码 //回调的函数 function alt(temp){ alert(temp); }; $("#Btn").click(function (obj) { //声 ...
- 插头DP题目泛做(为了对应WYD的课件)
题目1:BZOJ 1814 URAL 1519 Formula 1 题目大意:给定一个N*M的棋盘,上面有障碍格子.求一个经过所有非障碍格子形成的回路的数量. 插头DP入门题.记录连通分量. #inc ...
- C++服务器设计(一):基于I/O复用的Reactor模式
I/O模型选择 在网络服务端编程中,一个常见的情景是服务器需要判断多个已连接套接字是否可读,如果某个套接字可读,则读取该套接字数据,并进行进一步处理. 在最常用的阻塞式I/O模型中,我们对每个连接套接 ...
- OpenCV——Rect矩阵类
成员变量x.y.width.height,分别为左上角点的坐标和矩形的宽和高. 常用的成员函数有: Size()返回值为一个Size area()返回矩形的面积 contains(Point)用来判断 ...
- (转) 学习C++ -> 向量(vector)
vector是向量类型,它是一种对象实体,具有值,所以可以看作是变量. 它可以容纳许多其他类型的相同实体,如若干个整数,所以称其为容器. vector类与一般的Array类的区别在于: 1 ...
- Niagara AX之BajaScript资料哪里找
四个步骤:(开篇:多谢陈工!) 1.Services下添加box->boxService: 2.在Apps下添加BajaScriptTutorialsApp: 3.登录用户的Web Profil ...