浅谈JavaScript中的作用域和闭包问题


Posted in Javascript onJuly 07, 2015

JavaScript的作用域以函数为界,不同的函数拥有相对独立的作用域。函数内部可以声明和访问全局变量,也可以声明局部变量(使用var关键字,函数的参数也是局部变量),但函数外部无法访问内部的局部变量:

function test() {
var a = 0; // 局部变量
b = 1; // 全局变量
}
a = ?, b = ? // a为undefined,b为1

同名的局部变量会覆盖全局变量,但本质上它们是两个独立的变量,一方发生变化不会影响另一方:

a = 5; // 函数外a的值为5
function test() {
var a = 4; // 函数内a的值为4
}();
a = ? // 函数外a的值仍为5,不受函数影响

一般而言,函数结束后,对函数内部变量的引用全部结束,函数内的局部变量将被回收,函数的执行环境将被清空,但是,如果以内部函数作为函数的返回结果,情况就会发生变化:

function test(i) {
var b = i * i;
return function() {
return b--;
};
}
var a = test(8);
a(); // 返回值为64, 内部变量b为63
a(); // 返回值为63, 内部变量b为62

当以内部函数作为返回值时,因为函数结束后内部变量的引用并未结束,所以函数的局部变量无法回收,函数的执行环境被保留下来,因而形成了闭包效果,可以通过该引用访问本该被回收的内部变量。
闭包还使得函数的局部变量成为“私有”变量,只能通过返回的内部函数访问,而无法通过其他任何手段去改变。
因此,闭包可用于维持局部变量和保护变量。
不使用闭包的情况:

var a = []; // 假设a中包含5个元素
for (var i = 0, m = a.length; i < m; i++) {
a[i].onclick = function(e) {
return 'No. ' + i;
};
}
// 点击任何一个元素,返回值都是“No. 5”,因为i最后的值为5
使用闭包的情况:
function test(i) {
return function(e) {
return 'No. ' + i;
};
}
var a = []; // 假设a中包含5个元素
for (var i = 0, m = a.length; i < m; i++) {
a[i].onclick = test(i);
}
// 使用闭包维持局部变量,点击元素返回No. 0 ~ No. 4

闭包带来便利的同时,也会带来一些弊端:
1、程序复杂度增加,理解更加困难
2、干扰正常的垃圾回收,复杂的闭包还可能导致内存无法回收而崩溃
3、庞大的闭包往往伴随着性能问题
因此,闭包宜精简小巧,而不宜庞大复杂,同时应避免大规模的使用闭包。闭包的出现,本身是语言的一个bug,但是因为它独特的功能而保留下来。它是一个辅助手段,而不是主要功能。

Javascript 相关文章推荐
jQuery调用AJAX时Get和post公用的乱码解决方法实例说明
Jun 04 Javascript
javascript获取select的当前值示例代码(兼容IE/Firefox/Opera/Chrome)
Dec 17 Javascript
JavaScript的事件代理和委托实例分析
Mar 25 Javascript
javascript中关于&amp;&amp; 和 || 表达式的小技巧分享
Apr 10 Javascript
JavaScript判断IE版本型号
Jul 27 Javascript
js实现图片切换(动画版)
Dec 25 Javascript
jQuery插件form-validation-engine正则表达式操作示例
Feb 09 Javascript
javascript 开发之百度地图使用到的js函数整理
May 19 Javascript
vue-router 路由基础的详解
Oct 17 Javascript
关于angularJs清除浏览器缓存的方法
Nov 28 Javascript
vue 路由嵌套高亮问题的解决方法
May 17 Javascript
vue组件之间通信实例总结(点赞功能)
Dec 05 Javascript
深入分析下javascript中的[]()+!
Jul 07 #Javascript
javascript实现的多个层切换效果通用函数实例
Jul 06 #Javascript
javascript动态添加删除tabs标签的方法
Jul 06 #Javascript
Jsonp post 跨域方案
Jul 06 #Javascript
javascript运动详解
Jul 06 #Javascript
浅谈jQuery中height与width
Jul 06 #Javascript
jQuery中$this和$(this)的区别介绍(一看就懂)
Jul 06 #Javascript
You might like
PHP 输出简单动态WAP页面
2009/06/09 PHP
PHP删除目录及目录下所有文件的方法详解
2013/06/06 PHP
php加速器eAccelerator的配置参数、API详解
2014/05/05 PHP
PHP传值到不同页面的三种常见方式及php和html之间传值问题
2015/11/19 PHP
如何使用微信公众平台开发模式实现多客服
2016/01/06 PHP
PHP购物车类Cart.class.php定义与用法示例
2016/07/20 PHP
原生javascript实现图片轮播效果代码
2010/09/03 Javascript
基于JavaScript 声明全局变量的三种方式详解
2013/05/07 Javascript
使用JQuery在线制作ppt并在线演示源码特效
2015/09/08 Javascript
JavaScript设计模式经典之工厂模式
2016/02/24 Javascript
完美解决jQuery fancybox ie 无法显示关闭按钮的问题
2016/11/29 Javascript
AngularJs每天学习之总体介绍
2017/08/07 Javascript
Javascript(es2016) import和require用法和区别详解
2017/08/11 Javascript
20个最常见的jQuery面试问题及答案
2018/05/23 jQuery
Redux实现组合计数器的示例代码
2018/07/04 Javascript
vue 纯js监听滚动条到底部的实例讲解
2018/09/03 Javascript
JS中min函数实例讲解
2019/02/18 Javascript
Vue中通过Vue.extend动态创建实例的方法
2019/08/13 Javascript
使用konva和vue-konva库实现拖拽滑块验证功能
2020/04/27 Javascript
Python简单格式化时间的方法【strftime函数】
2016/09/18 Python
Python使用Flask-SQLAlchemy连接数据库操作示例
2018/08/31 Python
python3+requests接口自动化session操作方法
2018/10/13 Python
python画图的函数用法以及技巧
2019/06/28 Python
python生成requirements.txt的两种方法
2019/09/18 Python
Pytorch中Tensor与各种图像格式的相互转化详解
2019/12/26 Python
python已协程方式处理任务实现过程
2019/12/27 Python
Python pip install如何修改默认下载路径
2020/04/29 Python
django 实现后台从富文本提取纯文本
2020/07/02 Python
英国著名的小众美容品牌网站:Alyaka
2017/08/08 全球购物
lookfantastic荷兰:在线购买奢华护肤、护发和化妆品
2018/11/27 全球购物
在校硕士自我鉴定
2014/01/23 职场文书
2014年财务工作自我评价
2014/09/23 职场文书
2015年度物业公司工作总结
2015/04/27 职场文书
领导离职感言
2015/08/03 职场文书
关于艺术节的开幕致辞
2016/03/04 职场文书
CSS3实现的文字弹出特效
2021/04/16 HTML / CSS