浅谈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 相关文章推荐
javascript 全角转换实现代码
Jul 17 Javascript
jQuery 的全选(全非选)即取得被选中的值使用介绍
Nov 12 Javascript
javascript实时获取鼠标坐标值并显示的方法
Apr 30 Javascript
jquery实现点击变换导航样式的方法
Aug 31 Javascript
jQuery使用模式窗口实现在主页面和子页面中互相传值的方法
Mar 01 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
May 28 Javascript
express文件上传中间件Multer详解
Oct 24 Javascript
BootStrap实现轮播图效果(收藏)
Dec 30 Javascript
JavaScript基于activexobject连接远程数据库SQL Server 2014的方法
Jul 12 Javascript
使用AngularJS对表单提交内容进行验证的操作方法
Jul 12 Javascript
vue中如何使用ztree
Feb 06 Javascript
vue富文本编辑器组件vue-quill-edit使用教程
Sep 21 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
解决cPanel无法安装php5.2.17
2014/06/22 PHP
详细解读PHP的Yii框架中登陆功能的实现
2015/08/21 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
Mootools 1.2教程 同时进行多个形变动画
2009/09/15 Javascript
jquery UI 1.72 之datepicker
2009/12/29 Javascript
jquery 关键字“拖曳搜索”之“拖曳”以及 图片“提示自适应放大”效果 的实现
2010/04/18 Javascript
浅析Prototype的模板类 Template
2011/12/07 Javascript
JS中typeof与instanceof之间的区别总结
2013/11/14 Javascript
jQuery随机密码生成的方法
2015/03/09 Javascript
jQuery插件StickUp实现网页导航置顶
2015/04/12 Javascript
jQuery点击其他地方时菜单消失的实现方法
2016/04/22 Javascript
jQuery Ajax和getJSON获取后台普通json数据和层级json数据用法分析
2016/06/08 Javascript
关于在Servelet中如何获取当前时间的操作方法
2016/06/28 Javascript
使用微信内嵌H5网页解决JS倒计时失效问题
2017/01/13 Javascript
bootstrap-Treeview实现级联勾选
2017/11/23 Javascript
Javascript 之封装(Package)
2018/09/14 Javascript
Vue实现购物车详情页面的方法
2019/08/20 Javascript
[42:27]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#2Fnatic VS OG第三局
2016/03/05 DOTA
Python读写Excel文件的实例
2013/11/01 Python
详解 Python中LEGB和闭包及装饰器
2017/08/03 Python
PyQt5 QSerialPort子线程操作的实现
2018/04/21 Python
python判断输入日期为第几天的实例
2018/11/13 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
2019/04/16 Python
NumPy 数组使用大全
2019/04/25 Python
filter使用python3代码进行迭代元素的实例详解
2020/12/03 Python
canvas版人体时钟的实现示例
2021/01/29 HTML / CSS
百思买加拿大:Best Buy Canada
2018/03/20 全球购物
viagogo波兰票务平台:演唱会、体育比赛、戏剧门票
2018/04/23 全球购物
The Outnet亚太地区:折扣设计师时装店
2019/12/05 全球购物
应届生新闻编辑求职信
2013/11/19 职场文书
人力资源部经理助理岗位职责
2014/03/04 职场文书
英语三分钟演讲稿
2014/08/19 职场文书
小学教师节活动总结
2015/03/20 职场文书
元旦联欢晚会主持词
2015/07/01 职场文书
2015年学校消防安全工作总结
2015/10/14 职场文书
Python中rapidjson参数校验实现
2021/07/25 Python