浅谈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类型转换方法及需要注意的问题小结(挺全面)
Nov 11 Javascript
jquery怎样实现ajax联动框(一)
Mar 08 Javascript
JS中判断null、undefined与NaN的方法
Mar 26 Javascript
学习javascript面向对象 理解javascript对象
Jan 04 Javascript
js面向对象的写法
Feb 19 Javascript
MUI 上拉刷新/下拉加载功能实例代码
Apr 13 Javascript
webpack4 入门最简单的例子介绍
Sep 05 Javascript
Vue中UI组件库之Vuex与虚拟服务器初识
May 07 Javascript
Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示
Jun 26 Javascript
layui使用form表单实现post请求页面跳转的方法
Sep 14 Javascript
Vue router传递参数并解决刷新页面参数丢失问题
Dec 02 Vue.js
Vue常用API、高级API的相关总结
Feb 02 Vue.js
深入分析下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
dhtmlxTree目录树增加右键菜单以及拖拽排序的实现方法
2013/04/26 PHP
Codeigniter通过SimpleXML将xml转换成对象的方法
2015/03/19 PHP
php加密解密字符串示例
2016/10/13 PHP
PHP DB 数据库连接类定义与用法示例
2019/03/11 PHP
Yii框架where查询用法实例分析
2019/10/22 PHP
javascript 选择文件夹对话框(web)
2009/07/07 Javascript
javascript cookies操作集合
2010/04/12 Javascript
js微信分享API
2020/10/11 Javascript
ionic2 tabs使用 Modal底部tab弹出框
2016/12/30 Javascript
Angular中使用$watch监听object属性值的变化(详解)
2017/04/24 Javascript
基于Bootstrap表单验证功能
2017/11/17 Javascript
Vue+jquery实现表格指定列的文字收缩的示例代码
2018/01/09 jQuery
Bootstrap Table中的多选框删除功能
2018/07/15 Javascript
vuejs前后端数据交互之从后端请求数据的实例
2018/08/11 Javascript
详解JS中统计函数执行次数与执行时间
2018/09/04 Javascript
JavaScript实现选项卡效果的分析及步骤
2019/04/16 Javascript
Node.js 获取微信JS-SDK CONFIG的方法示例
2019/05/21 Javascript
VUE路由动态加载实例代码讲解
2019/08/26 Javascript
keep-alive保持组件状态的方法
2020/12/02 Javascript
Python for Informatics 第11章之正则表达式(四)
2016/04/21 Python
Linux-ubuntu16.04 Python3.5配置OpenCV3.2的方法
2018/04/02 Python
python3 拼接字符串的7种方法
2018/09/12 Python
Python操作远程服务器 paramiko模块详细介绍
2019/08/07 Python
python将三维数组展开成二维数组的实现
2019/11/30 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
TensorFlow基本的常量、变量和运算操作详解
2020/02/03 Python
python归并排序算法过程实例讲解
2020/11/04 Python
使用CSS3在触屏上为按钮实现激活效果
2013/09/27 HTML / CSS
优秀民警事迹材料
2014/01/29 职场文书
庆中秋节主题活动方案
2014/02/03 职场文书
孝敬父母的演讲稿
2014/05/14 职场文书
迎新春趣味活动方案
2014/08/24 职场文书
五五普法心得体会
2014/09/04 职场文书
毕业生见习报告总结
2014/11/08 职场文书
Python办公自动化解决world文件批量转换
2021/09/15 Python
MySQL数据库中的锁、解锁以及删除事务
2022/05/06 MySQL