理解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 相关文章推荐
判断目标是否是window,document,和拥有tagName的Element的代码
May 31 Javascript
优化Jquery,提升网页加载速度
Nov 14 Javascript
ECMAScript5中的对象存取器属性:getter和setter介绍
Dec 08 Javascript
node.js中的buffer.length方法使用说明
Dec 14 Javascript
js+jquery实现图片裁剪功能
Jan 02 Javascript
javascript实现下班倒计时效果的方法(可桌面通知)
Jul 10 Javascript
Bootstrap每天必学之导航条(二)
Mar 01 Javascript
zTree插件下拉树使用入门教程
Apr 11 Javascript
JavaScript实现类似淘宝的购物车效果
Mar 16 Javascript
jquery ajax异步提交表单数据的方法
Oct 27 jQuery
Vue-cropper 图片裁剪的基本原理及思路讲解
Apr 17 Javascript
Jquery属性的获取/设置及样式添加/删除操作技巧分析
Dec 23 jQuery
理解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
图象函数中的中文显示
2006/10/09 PHP
php中拷贝构造函数、赋值运算符重载
2012/07/25 PHP
php判断访问IP的方法
2015/06/19 PHP
64位windows系统下安装Memcache缓存
2015/12/06 PHP
使用php从身份证号中获取一系列线索(星座、生肖、生日等)
2016/05/11 PHP
PHP递归遍历指定文件夹内的文件实现方法
2016/11/15 PHP
PHP 信号管理知识整理汇总
2017/02/19 PHP
javascript new一个对象的实质
2010/01/07 Javascript
jQuery模拟超链接点击效果代码
2013/04/21 Javascript
JavaScript 事件对象介绍
2015/04/13 Javascript
javascript实现选中复选框后相关输入框变灰不可用的方法
2015/08/11 Javascript
JavaScript String 对象常用方法详解
2016/05/13 Javascript
jQuery基本选择器(实例及表单域value的获取方法)
2016/05/20 Javascript
VueJS组件之间通过props交互及验证的方式
2017/09/04 Javascript
基于ES6 Array.of的用法(实例讲解)
2017/09/05 Javascript
js 图片转base64的方式(两种)
2018/04/24 Javascript
jQuery 获取除某指定对象外的其他对象 ( :not() 与.not())
2018/10/10 jQuery
详解基于Vue,Nginx的前后端不分离部署教程
2018/12/04 Javascript
vue动态设置路由权限的主要思路
2021/01/13 Vue.js
django用户注册、登录、注销和用户扩展的示例
2018/03/19 Python
python实现多人聊天室
2020/03/31 Python
在pycharm中使用git版本管理以及同步github的方法
2019/01/16 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
2019/04/16 Python
网易微博Web App用HTML5开发的过程介绍
2012/06/13 HTML / CSS
美国现代家具和家居商店:Apt2B
2016/08/29 全球购物
美国知名的时尚购物网站:Anthropologie
2016/12/22 全球购物
大学生就业自我推荐信
2014/05/10 职场文书
个人委托书怎么写
2014/09/17 职场文书
2015年母亲节寄语
2015/03/23 职场文书
企业办公室主任岗位职责
2015/04/01 职场文书
2015年世界急救日宣传活动方案
2015/05/06 职场文书
python实现批量移动文件
2021/04/05 Python
教你用Java在个人电脑上实现微信扫码支付
2021/06/13 Java/Android
MySQL慢查询优化解决问题
2022/03/17 MySQL
PostgreSQL出现死锁该如何解决
2022/05/30 PostgreSQL
Python如何利用pandas读取csv数据并绘图
2022/07/07 Python