浅谈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中Get和Set访问器的实现代码
Sep 19 Javascript
JavaScript中函数声明优先于变量声明的实例分析
Mar 01 Javascript
在Node.js中实现文件复制的方法和实例
Jun 05 Javascript
JS实现完全语义化的网页选项卡效果代码
Sep 15 Javascript
使用do...while的方法输入一个月中所有的周日(实例代码)
Jul 22 Javascript
基于Vue2.X的路由和钩子函数详解
Feb 09 Javascript
Vue.js 表单控件操作小结
Mar 29 Javascript
Node.js命令行/批处理中如何更改Linux用户密码浅析
Jul 22 Javascript
新版小程序登录授权的方法
Dec 12 Javascript
详解vue-property-decorator使用手册
Jul 29 Javascript
微信小程序JS加载esmap地图的实例详解
Sep 04 Javascript
jquery插件懒加载的示例
Oct 24 jQuery
深入分析下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日期处理函数 整型日期格式
2011/01/12 PHP
php中adodbzip类实例
2014/12/08 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
CSS常用网站布局实例
2008/04/03 Javascript
JS对img进行操作(换图片/切图/轮换/停止)
2013/04/17 Javascript
jQuery瀑布流插件Wookmark使用实例
2014/04/02 Javascript
JS 排序输出实现table行号自增前端动态生成的tr
2014/08/13 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
理解和运用JavaScript的闭包机制
2015/08/13 Javascript
JavaScript Date对象详解
2016/03/01 Javascript
第一篇初识bootstrap
2016/06/21 Javascript
JavaScript使用键盘输入控制实现数字验证功能
2016/08/19 Javascript
jQueryUI 拖放排序遇到滚动条时有可能无法执行排序的小bug及解决方案
2016/12/19 Javascript
轻松理解JavaScript闭包
2017/03/14 Javascript
vue-router路由参数刷新消失的问题解决方法
2017/06/17 Javascript
bootstrap中日历范围选择插件daterangepicker的使用详解
2018/04/17 Javascript
JS原生带缩略图的图片切换效果
2018/10/10 Javascript
JS左右无缝轮播功能完整实例
2019/05/16 Javascript
什么时候不能在 Node.js 中使用 Lock Files
2019/06/24 Javascript
vue router总结 $router和$route及router与 router与route区别
2019/07/05 Javascript
js的Object.assign用法示例分析
2020/03/05 Javascript
解决js中的setInterval清空定时器不管用问题
2020/11/17 Javascript
Python使用urllib2获取网络资源实例讲解
2013/12/02 Python
python多重继承新算法C3介绍
2014/09/28 Python
python分析nignx访问日志脚本分享
2015/02/26 Python
python数据清洗系列之字符串处理详解
2017/02/12 Python
浅谈Django中的数据库模型类-models.py(一对一的关系)
2018/05/30 Python
基于python实现文件加密功能
2020/01/06 Python
pytorch 实现模型不同层设置不同的学习率方式
2020/01/06 Python
Python unittest单元测试框架实现参数化
2020/04/29 Python
Django全局启用登陆验证login_required的方法
2020/06/02 Python
结构工程个人自荐信范文
2013/11/30 职场文书
优秀应届毕业生推荐信
2014/02/18 职场文书
青蓝工程实施方案
2014/03/27 职场文书
小学生表扬稿范文
2015/05/05 职场文书
SQL Server中搜索特定的对象
2022/05/25 SQL Server