浅谈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实用代码片段集合
Aug 12 Javascript
JS 退出系统并跳转到登录界面的实现代码
Jun 29 Javascript
IE下使用jQuery重置iframe地址时内存泄露问题解决办法
Feb 05 Javascript
Jquery遍历Json数据的方法
Apr 20 Javascript
包含中国城市的javascript对象实例
Aug 03 Javascript
深入php面向对象、模式与实践
Feb 16 Javascript
node.js遍历目录的方法示例
Aug 01 Javascript
微信小程序之判断页面滚动方向的示例代码
Aug 30 Javascript
微信小程序:数据存储、传值、取值详解
May 07 Javascript
对layui中的onevent 和event的使用详解
Sep 06 Javascript
微信小程序 自定义弹窗实现过程(附代码)
Dec 05 Javascript
vue之封装多个组件调用同一接口的案例
Aug 11 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
DOTA2 1月28日更新:监管系统降临刀塔世界
2021/01/28 DOTA
Discuz板块横排显示图片的实现方法
2007/05/28 PHP
PHP 解决utf-8和gb2312编码转换问题
2010/03/18 PHP
php下正则来匹配dede模板标签的代码
2010/08/21 PHP
PHP中的正则表达式实例详解
2017/04/25 PHP
PHP多种序列化/反序列化的方法详解
2017/06/23 PHP
利用js对象弹出一个层
2008/03/26 Javascript
JavaScript 新手24条实用建议[TUTS+]
2009/06/21 Javascript
jQuery 树形结构的选择器
2010/02/15 Javascript
jQuery UI Dialog 创建友好的弹出对话框实现代码
2012/04/12 Javascript
js函数的延迟加载实现代码
2012/10/11 Javascript
js监听键盘事件示例代码
2013/07/26 Javascript
jQuery打字效果实现方法(附demo源码下载)
2015/12/18 Javascript
深入探究AngularJS框架中Scope对象的超级教程
2016/01/04 Javascript
jQuery实现鼠标跟随提示层效果代码(可显示文本,Div,Table,Html等)
2016/04/18 Javascript
Javarscript中模块(module)、加载(load)与捆绑(bundle)详解
2017/05/28 Javascript
理解nodejs的stream和pipe机制的原理和实现
2017/08/12 NodeJs
[原创]jQuery实现合并/追加数组并去除重复项的方法
2018/04/11 jQuery
详解Vue2.0配置mint-ui踩过的那些坑
2018/04/23 Javascript
JS中的两种数据类型及实现引用类型的深拷贝的方法
2018/08/12 Javascript
详解webpack自定义loader初探
2018/08/29 Javascript
NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法
2018/10/17 NodeJs
JavaScript实现消消乐的源代码
2021/01/12 Javascript
在Windows8上的搭建Python和Django环境
2014/07/03 Python
Python基础学习之时间转换函数用法详解
2019/06/18 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
使用python快速在局域网内搭建http传输文件服务的方法
2019/11/14 Python
Pytorch: 自定义网络层实例
2020/01/07 Python
美国设计师精美珠宝购物网:Netaya
2016/08/28 全球购物
Rockport乐步美国官网:风靡美国的白宫鞋
2016/11/24 全球购物
Currentbody美国/加拿大:美容仪专家
2020/03/09 全球购物
琳达·法罗眼镜英国官网:Linda Farrow英国
2021/01/19 全球购物
便利店的创业计划书
2014/01/15 职场文书
赞美老师的演讲稿
2014/05/22 职场文书
担保书范文
2019/07/09 职场文书
创业计划书之游泳馆
2019/09/16 职场文书