浅谈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 1.4.2发布!主要是性能与API
Feb 25 Javascript
JSON中双引号的轮回使用过程中一定要小心
Mar 05 Javascript
jQuery 写的简单打字游戏可以提示正确和错误的次数
Jul 01 Javascript
node.js调用C++开发的模块实例
Jul 03 Javascript
javascript实现tab切换的四种方法
Nov 05 Javascript
jQuery+css实现非常漂亮的水平导航菜单效果
Jul 27 Javascript
一个超简单的jQuery回调函数例子(分享)
Aug 08 Javascript
基于JS分页控件实现简单美观仿淘宝分页按钮效果
Nov 07 Javascript
AngularJS实现单一页面内设置跳转路由的方法
Jun 28 Javascript
jQuery UI Draggable + Sortable 结合使用(实例讲解)
Sep 07 jQuery
node puppeteer(headless chrome)实现网站登录
May 09 Javascript
微信小程序登录数据解密及状态维持实例详解
May 06 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对称加密算法示例
2014/05/07 PHP
ThinkPHP控制器间实现相互调用的方法
2014/10/31 PHP
作为程序员必知的16个最佳PHP库
2015/12/09 PHP
PHP在线书签系统分享
2016/01/04 PHP
Jquery replace 字符替换实现代码
2010/12/02 Javascript
js动态给table添加/删除tr的方法
2013/08/02 Javascript
js获取通过ajax返回的map型的JSONArray的方法
2014/01/09 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
2015/01/22 Javascript
网页前端登录js按Enter回车键实现登陆的两种方法
2016/05/10 Javascript
微信小程序 获取相册照片实例详解
2016/11/16 Javascript
完美解决axios在ie下的兼容性问题
2018/03/05 Javascript
深入浅析Vue.js计算属性和侦听器
2018/05/05 Javascript
element-ui带输入建议的input框踩坑(输入建议空白以及会闪出上一次的输入建议问题)
2019/01/15 Javascript
vue实现将一个数组内的相同数据进行合并
2019/11/07 Javascript
vue-cli设置css不生效的解决方法
2020/02/07 Javascript
JavaScript实现动态生成表格
2020/08/02 Javascript
简单的Python的curses库使用教程
2015/04/11 Python
Python画图学习入门教程
2016/07/01 Python
python3安装crypto出错及解决方法
2019/07/30 Python
让你的Python代码实现类型提示功能
2019/11/19 Python
浅析Django中关于session的使用
2019/12/30 Python
Python3 mmap内存映射文件示例解析
2020/03/23 Python
给ubuntu18安装python3.7的详细教程
2020/06/08 Python
HTML5在canvas中绘制复杂形状附效果截图
2014/06/23 HTML / CSS
Crabtree & Evelyn英国官网:瑰珀翠护手霜、香水、沐浴和身体护理
2018/04/26 全球购物
作为网站管理者应当如何防范XSS
2014/08/16 面试题
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的
2015/07/24 面试题
创业计划书六个要素
2013/12/26 职场文书
幼儿教师工作感言
2014/02/14 职场文书
戒毒悔改检讨书
2014/09/21 职场文书
给上级领导的感谢信
2015/01/22 职场文书
教研活动主持词
2015/07/03 职场文书
优秀党员主要事迹材料
2015/11/04 职场文书
读《教育心理学》心得体会
2016/01/22 职场文书
导游词之山西祁县乔家大院
2019/10/14 职场文书
Java日常练习题,每天进步一点点(38)
2021/07/26 Java/Android