浅谈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 相关文章推荐
LBS blog sql注射漏洞[All version]-官方已有补丁
Aug 26 Javascript
JavaScript 弹出窗体点击按钮返回选择数据的实现
Apr 01 Javascript
单击复制文字兼容各浏览器的完美解决方案
Jul 04 Javascript
JavaScript自定义事件介绍
Aug 29 Javascript
jquery获取及设置outerhtml的方法
Mar 09 Javascript
学习JavaScript设计模式(接口)
Nov 26 Javascript
js获取鼠标点击的对象,点击另一个按钮删除该对象的实现代码
May 13 Javascript
js实现点击切换checkbox背景图片的简单实例
May 08 Javascript
利用jQuery实现简单的拖曳效果实例代码
Oct 20 jQuery
javascript(基于jQuery)实现鼠标获取选中的文字示例【测试可用】
Oct 26 jQuery
KnockoutJS数组比较算法实例详解
Nov 25 Javascript
详解Node.js使用token进行认证的简单示例
May 25 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微信支付之APP支付方法
2015/03/04 PHP
PHP中Session可能会引起并发问题
2015/06/26 PHP
thinkPHP5.0框架配置格式、加载解析与读取方法
2017/03/17 PHP
基于jquery的web页面日期格式化插件
2011/11/15 Javascript
javascript生成json数据简单示例分享
2014/02/14 Javascript
利用JavaScript检测CPU使用率自己写的
2014/03/22 Javascript
jQuery is()函数用法3例
2014/05/06 Javascript
node.js中的buffer.Buffer.byteLength方法使用说明
2014/12/10 Javascript
jQuery图片左右滚动代码 有左右按钮实例
2016/06/20 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
js中删除数组中的某一元素实例(无下标时)
2017/02/28 Javascript
ligerUI---ListBox(列表框可移动的实例)
2017/11/28 Javascript
利用JS测试目标网站的打开响应速度
2017/12/01 Javascript
vue-cli与webpack处理静态资源的方法及webpack打包的坑
2018/05/15 Javascript
jQuery实现的简单拖拽功能示例【测试可用】
2018/08/14 jQuery
原生js canvas实现鼠标跟随效果
2020/08/02 Javascript
Random 在 Python 中的使用方法
2018/08/09 Python
Python 给下载文件显示进度条和下载时间的实现
2020/04/02 Python
利用keras使用神经网络预测销量操作
2020/07/07 Python
详解java调用python的几种用法(看这篇就够了)
2020/12/10 Python
耐克巴西官方网站:Nike巴西
2016/08/14 全球购物
安德玛比利时官网:Under Armour比利时
2019/08/28 全球购物
营业员个人总结的自我评价
2013/10/25 职场文书
无故旷工检讨书
2014/01/26 职场文书
服装电子商务创业计划书
2014/01/30 职场文书
合伙经营协议书范本
2014/04/18 职场文书
国旗下的演讲稿
2014/05/08 职场文书
微笑面对生活演讲稿
2014/05/13 职场文书
党员群众路线个人整改措施思想汇报
2014/10/12 职场文书
简单的辞职信怎么写
2015/02/28 职场文书
硕士学位申请报告
2015/05/15 职场文书
教师见习总结范文
2015/06/23 职场文书
2016年感恩节寄语
2015/12/07 职场文书
2016年乡镇综治宣传月活动总结
2016/03/16 职场文书
SpringBoot整合RabbitMQ的5种模式实战
2021/08/02 Java/Android
解析mybatis-plus中的resultMap简单使用
2021/11/23 Java/Android