轻松学习Javascript闭包


Posted in Javascript onMarch 01, 2017

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

当function里嵌套function时,内部的function可以访问外部function里的变量。

function foo(x) {
 var tmp = 3;
 function bar(y) {
  alert(x + y + (++tmp));
 }
 bar(10);
}
foo(2)

不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问foo的变量tmp。

但,这还不是闭包。当你return的是内部function时,就是一个闭包。内部function会close-over外部function的变量直到内部function结束。

function foo(x) {
 var tmp = 3;
 return function (y) {
  alert(x + y + (++tmp));
 }
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);

上面的脚本最终也会alert 16,因为虽然bar不直接处于foo的内部作用域,但bar还是能访问x和tmp。

但是,由于tmp仍存在于bar闭包的内部,所以它还是会自加1,而且你每次调用bar时它都会自加1.

(考虑到六岁这个限制:我们其实可以建立不止一个闭包方法,比如return它们的数组,也可以把它们设置为全局变量。它们全都指向相同的x和相同的tmp,而不是各自有一份副本。)

注:现在来整点儿七岁的内容。

上面的x是一个字面值(值传递),和JS里其他的字面值一样,当调用foo时,实参x的值被复制了一份,复制的那一份作为了foo的参数x。

那么问题来了,JS里处理object时是用到引用传递的,那么,你调用foo时传递一个object,foo函数return的闭包也会引用最初那个object!

function foo(x) {
var tmp = 3;
return function (y) {
 alert(x + y + tmp);
 x.memb = x.memb ? x.memb + 1 : 1;
 alert(x.memb);
 }
}
var age = new Number(2);
var bar = foo(age); // bar 现在是一个引用了age的闭包
bar(10);

不出我们意料,每次运行bar(10),x.memb都会自加1。但需要注意的是x每次都指向同一个object变量——age,运行两次bar(10)后,age.memb会变成2.

这和HTML对象的内存泄漏有关,呃,不过貌似超出了答题的范围。

这里有一个不用return关键字的闭包例子:

function closureExample(objID, text, timedelay) { 
  setTimeout(function() { 
    document.getElementById(objID).innerHTML = text; 
  }, timedelay); 
} 
closureExample(‘myDiv', ‘Closure is created', 500); 

JS里的function能访问它们的:

1. 参数

2. 局部变量或函数

3. 外部变量(环境变量?),包括

3.1 全局变量,包括DOM。

3.2 外部函数的变量或函数。

如果一个函数访问了它的外部变量,那么它就是一个闭包。

注意,外部函数不是必需的。通过访问外部变量,一个闭包可以维持(keep alive)这些变量。在内部函数和外部函数的例子中,外部函数可以创建局部变量,并且最终退出;但是,如果任何一个或多个内部函数在它退出后却没有退出,那么内部函数就维持了外部函数的局部数据。

一个典型的例子就是全局变量的使用。

闭包经常用于创建含有隐藏数据的函数(但并不总是这样)。

var db = (function() {
// 创建一个隐藏的object, 这个object持有一些数据
// 从外部是不能访问这个object的
var data = {};
// 创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {
  if (val === undefined) { return data[key] } // get
  else { return data[key] = val } // set
  }
// 我们可以调用这个匿名方法
// 返回这个内部函数,它是一个闭包
})();
db('x'); // 返回 undefined
db('x', 1); // 设置data['x']为1
db('x'); // 返回 1
// 我们不可能访问data这个object本身
// 但是我们可以设置它的成员

下面看下使用闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

以上所述是小编给大家介绍的Javascript闭包知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
getComputedStyle与currentStyle获取样式(style/class)
Mar 19 Javascript
基于jquery实现发送文章到手机的代码
Dec 26 Javascript
浅谈js函数的多种定义方法与区别
Nov 29 Javascript
简单实现JS上传图片预览功能
Apr 14 Javascript
如何理解Vue的render函数的具体用法
Aug 30 Javascript
Node.js 使用递归实现遍历文件夹中所有文件
Sep 18 Javascript
iview给radio按钮组件加点击事件的实例
Sep 30 Javascript
vue路由拦截及页面跳转的设置方法
May 24 Javascript
apicloud拉起小程序并传递参数的方法示例
Nov 21 Javascript
Vue使用NProgress的操作过程解析
Oct 10 Javascript
vue-resource post数据时碰到Django csrf问题的解决
Mar 13 Javascript
支付宝小程序实现省市区三级联动
Jun 21 Javascript
js图片延迟加载(Lazyload)三种实现方式
Mar 01 #Javascript
node.js实现回调的方法示例
Mar 01 #Javascript
JQ中$(window).load和$(document).ready区别与执行顺序
Mar 01 #Javascript
Angular2库初探
Mar 01 #Javascript
浅谈angular2的http请求返回结果的subcribe注意事项
Mar 01 #Javascript
JavaScript两个变量交换值的实现方法
Mar 01 #Javascript
js实现仿购物车加减效果
Mar 01 #Javascript
You might like
如何正确理解PHP的错误信息
2006/10/09 PHP
php下通过伪造http头破解防盗链的代码
2010/07/03 PHP
php中实现可以返回多个值的函数实例
2015/03/21 PHP
laravel自定义分页的实现案例offset()和limit()
2019/10/15 PHP
比较简单的异步加载JS文件的代码
2009/07/18 Javascript
让firefox支持IE的一些方法的javascript扩展函数代码
2010/01/02 Javascript
js为数字添加逗号并格式化数字的代码
2013/08/23 Javascript
jquery获取元素值的方法(常见的表单元素)
2013/11/15 Javascript
jquery默认校验规则整理
2014/03/24 Javascript
JS+CSS实现感应鼠标渐变显示DIV层的方法
2015/02/20 Javascript
JS鼠标拖拽实例分析
2015/11/23 Javascript
谈谈第三方App接入微信登录 解读
2016/12/27 Javascript
JavaScript BASE64算法实现(完美解决中文乱码)
2017/01/10 Javascript
EasyUi 打开对话框后控件赋值及赋值后不显示的问题解决办法
2017/01/19 Javascript
js实现放大镜特效
2017/05/18 Javascript
jquery实现楼层滚动效果
2018/01/01 jQuery
JsChart组件使用详解
2018/03/04 Javascript
js实现掷骰子小游戏
2019/10/24 Javascript
python中常用的各种数据库操作模块和连接实例
2014/05/29 Python
python中的sort方法使用详解
2014/07/25 Python
优化Python代码使其加快作用域内的查找
2015/03/30 Python
Sanic框架安装与简单入门示例
2018/07/16 Python
python按照多个条件排序的方法
2019/02/08 Python
Python3.5常见内置方法参数用法实例详解
2019/04/29 Python
Python为何不能用可变对象作为默认参数的值
2019/07/01 Python
python之yield和Generator深入解析
2019/09/18 Python
Python Sphinx使用实例及问题解决
2020/01/17 Python
Python从MySQL数据库中面抽取试题,生成试卷
2021/01/14 Python
西班牙香水和化妆品连锁店:Druni
2019/05/05 全球购物
优秀毕业生推荐信
2013/11/02 职场文书
师范毕业生个人求职信
2013/12/09 职场文书
股东合作协议书
2014/04/14 职场文书
情况说明书怎么写
2015/10/08 职场文书
MySQL锁机制
2021/04/05 MySQL
浅谈Mysql多表连接查询的执行细节
2021/04/24 MySQL
python的变量和简单数字类型详解
2021/09/15 Python