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中却经常让我觉 ...
随机推荐
- java的Future使用方法
首先,Future是一个接口,该接口用来返回异步的结果. package com.itbuluoge.mythread; import java.util.ArrayList; import java ...
- [置顶] 【cocos2d-x入门实战】微信飞机大战之十二:分数的本地存储
转载请表明地址:http://blog.csdn.net/jackystudio/article/details/12036237 作为一个单机游戏,连分数存储的的功能都没有,让它怎么在单机游戏圈里混 ...
- Android应用程序绑定服务(bindService)的过程源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6745181 Android应用程序组件Serv ...
- ORA-25154/ORA-01748
SQL> select oi.order_id,product_id,order_date from order_items oi join orders o using(order_id) w ...
- 解决ERROR 2006 (HY000): MySQL server has gone away
刚把博客从百度云搬到腾讯云,发现文章少了几篇.当时在导入dump数据的时候,就曾经发现mysql提示: ERROR 2006 (HY000): MySQL server has gone away N ...
- 前端判断用户请求是PC还是移动端
链接:https://www.zhihu.com/question/20004700/answer/13678113 第一步先在服务器端使用User Agent判断,先匹配出移动设备,这一步可以统计U ...
- 解决ScrollView嵌套ListView和GridView冲突的方法
本文摘抄自:http://blog.csdn.net/yuhailong626/article/details/20639217 原文地址:http://blog.csdn.net/yuhailong ...
- jQuery Moblile Demos学习记录Panel
jQuery Moblile Demos学习记录Panel 11. 二 / Jquery Mobile / 没有评论 本文来源于www.ifyao.com禁止转载!www.ifyao.com 我就 ...
- HibernateTemplate类的方法flush()
hibernate的实体都是存储在缓存中的,所以你会发现有的时候当你创建出两个主键相通的实体的时候会报错.正常情况是当你调用save方法的时候,这个实体对象未必已经保存到数据库了,调用close方法的 ...
- python3.4+pyspider爬58同城(二)
之前使用python3.4+selenium实现了爬58同城的详细信息,这次用pyspider实现,网上搜了下,目前比较流行的爬虫框架就是pyspider和scrapy,但是scrapy不支持pyth ...