理解Javascript_15_作用域分配与变量访问规则,再送个闭包


Posted in Javascript onOctober 20, 2010

作用域分配与变量访问规则

在 ECMAScript 中,函数也是对象。函数对象在变量实例化过程中会根据函数声明来创建,或者是在计算函数表达式或调用 Function 构造函数时创建。(关于'函数对象'请见《理解Javascript_08_函数对象》)。每个函数对象都有一个内部的 [[scope]] 属性,这个属性也由对象列表(链)组成。这个内部的[[scope]] 属性引用的就是创建它们的执行环境的作用域链,同时,当前执行环境的活动对象被添加到该对象列表的顶部。当我们在函数内部访问变量时,其实就是在作用域链上寻找变量的过程。

理论性太强了(总结死我了!),还是让我们来看一段代码吧:

<script type="text/javascript"> 
function outer(){ 
var i = 10; 
function inner(){ 
var j = 100; 
alert(j);//100 
alert(i);//10 
alert(adf); 
} 
inner(); 
} 
outer(); 
</script>

下图清晰的展现了上述代码的内存分配与作用域分配情况:
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
下面来解释一下:
1.载入代码,创建全局执行环境,此时会在可变对象(window)中添加outer变量,其指向于函数对象outer,此时作用域链中只有window对象.
2.执行代码,当程序执行到outer()时,会在全局对象中寻找outer变量,成功调用。
3.创建outer的执行环境,此时会新创建一个活动对象,添加变量i,设置值为10,添加变量inner,指向于函数对象inner.并将活动对象压入作用域链中.并将函数对象outer的[[scope]]属性指向活动对象outer。此时作用域链为outer的活动对象+window.
4.执行代码,为 i 成功赋值。当程序执行到inner()时,会在函数对象outer的[[scope]]中寻找inner变量。找到后成功调用。
5.创建inner的执行环境,新建一个活动对象,添加变量j,赋值为100,并将该活动对象压入作用域链中,并函数对象inner的[[scope]]属性指向活动对象inner.此时作用域链为:inner的活动对象+outer的活动对象+全局对象.
6.执行代码为j赋值,当访问i、j时成功在作用域中找到对应的值并输出,而当访问变量adf时,没有在作用域中寻找到,访问出错。

注:通过内存图,我们会发现作用域链与prototype链是如此的相象。这说明了很多问题...(仁者见仁智者见智,自己探寻答案吧!)

闭包原理
在我们了解了作用域的问题之后,对于闭包这个问题已经很简单了。什么是闭包?闭包就是封闭了外部函数作用域中变量的内部函数。
我们来看一个典型的闭包运用:生成increment值

<script type="text/javascript"> 
var increment = (function(){ 
var id = 0; 
return function(){ 
return ++id; 
} 
})() 
alert(increment());//1 
alert(increment());//2 
</script>

外层匿名函数返回的是一个内嵌函数,内嵌函数使用了外层匿名函数的局部变量id。照理外层匿名函数的局部变量在返回时就超出了作用域因此increment()调用无法使用才对。这就是闭包Closure,即函数调用返回了一个内嵌函数,而内嵌函数引用了外部函数的局部变量、参数等这些应当被关闭(Close)了的资源。这是怎么一回事呢?让我们来寻找答案:
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
根据Scope Chain的理解可以解释,返回的内嵌函数已经持有了构造它时的Scope Chain,虽然outer返回导致这些对象超出了作用域、生存期范围,但JavaScript使用自动垃圾回收来释放对象内存: 按照规则定期检查,对象没有任何引用才被释放。因此上面的代码能够正确运行。

参考:
http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html
http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html

Javascript 相关文章推荐
JavaScript asp.net 获取当前超链接中的文本
Apr 14 Javascript
window.js 主要包含了页面的一些操作
Dec 23 Javascript
jquery 事件冒泡的介绍以及如何阻止事件冒泡
Dec 25 Javascript
循环 vs 递归浅谈
Feb 28 Javascript
jQuery实现简单的间隔向上滚动效果
Mar 09 Javascript
js文本框走动跑马灯效果代码分享
Aug 25 Javascript
基于jQuery实现的QQ表情插件
Aug 25 Javascript
BootStrap 智能表单实战系列(五) 表单依赖插件处理
Jun 13 Javascript
js 截取或者替换字符串中的数字实现方法
Jun 13 Javascript
Bootstrap Tree View简单而优雅的树结构组件实例解析
Jun 15 Javascript
Mac中安装nvm的教程分享
Dec 11 Javascript
vue element-ui实现动态面包屑导航
Dec 23 Javascript
理解Javascript_14_函数形式参数与arguments
Oct 20 #Javascript
理解Javascript_13_执行模型详解
Oct 20 #Javascript
用jquery与css打造个性化的单选框和复选框
Oct 20 #Javascript
Jquery插件之多图片异步上传
Oct 20 #Javascript
jquery判断checkbox(复选框)是否被选中的代码
Oct 20 #Javascript
jQuery下扩展插件和拓展函数的写法(匿名函数使用的典型例子)
Oct 20 #Javascript
JQuery 拾色器插件发布-jquery.icolor.js
Oct 20 #Javascript
You might like
S900/ ETON E1-XM 收音机
2021/03/02 无线电
php更改目录及子目录下所有的文件后缀扩展名的代码
2010/10/12 PHP
PHP计算指定日期所在周的开始和结束日期的方法
2015/03/24 PHP
在WordPress中使用wp-cron插件来设置定时任务
2015/12/10 PHP
Ajax+PHP实现的分类列表框功能示例
2019/02/11 PHP
使用jQuery简化Ajax开发 Ajax开发入门
2009/10/14 Javascript
自己写了一个展开和收起的多更能型的js效果
2013/03/05 Javascript
JQuery EasyUI 数字格式化处理示例
2014/05/05 Javascript
使用nodejs、Python写的一个简易HTTP静态文件服务器
2014/07/18 NodeJs
网站接入QQ登录的两种方法
2014/07/22 Javascript
javascript常用方法汇总
2014/12/02 Javascript
JavaScript过滤字符串中的中文与空格方法汇总
2016/03/07 Javascript
AngularJS 依赖注入详解和简单实例
2016/07/28 Javascript
一个极为简单的requirejs实现方法
2016/10/20 Javascript
AngularJS使用ng-repeat和ng-if实现数据的删选显示效果示例【适用于表单数据的显示】
2016/12/13 Javascript
xmlplus组件设计系列之按钮(2)
2017/04/26 Javascript
基于LayUI实现前端分页功能的方法
2017/07/22 Javascript
分析javascript中9 个常见错误阻碍你进步
2017/09/18 Javascript
AngularJS实现的简单拖拽功能示例
2018/01/02 Javascript
vue使用监听实现全选反选功能
2018/07/06 Javascript
layui关闭层级、简单监听的实例
2019/09/06 Javascript
跟老齐学Python之大话题小函数(1)
2014/10/10 Python
快速实现基于Python的微信聊天机器人示例代码
2017/03/03 Python
python机器学习之神经网络(一)
2017/12/20 Python
Python实现批量压缩图片
2018/01/25 Python
如何使用VSCode愉快的写Python于调试配置步骤
2018/04/06 Python
解决python os.mkdir创建目录失败的问题
2018/10/16 Python
python语音识别指南终极版(有这一篇足矣)
2020/09/09 Python
python uuid生成唯一id或str的最简单案例
2021/01/13 Python
拉斯维加斯城市观光通行证:Las Vegas Pass
2019/05/21 全球购物
程序员经常用到的UNIX命令
2015/04/13 面试题
团工委书记自荐书范文
2013/12/17 职场文书
2014年新生军训方案
2014/05/01 职场文书
三分钟自我介绍演讲稿
2014/08/21 职场文书
2015年教师党员承诺书
2015/04/27 职场文书
干货:企业内部人才推荐奖励方案!
2019/07/09 职场文书