通过示例彻底搞懂js闭包


Posted in Javascript onAugust 10, 2017

例1

function sayHello(name) 
{
 var text = 'Hello ' + name;
 var sayAlert = function() { console.log(text); }
 sayAlert();
}

sayHello("Bob") // 输出"Hello Bob"

在sayHello()函数中定义并调用了sayAlert()函数;sayAlert()作为内层函数,可以访问外层函数sayHello()中的text变量。

例2

function sayHello2(name) 
{
 var text = 'Hello ' + name; // 局部变量
 var sayAlert = function() { console.log(text); }
 return sayAlert;
}

var say2 = sayHello2("Jane");
say2(); // 输出"Hello Jane"

例3

function buildList(list) {
 var result = [];
 for(var i = 0; i < list.length; i++) {
  var item = 'item' + list[i];
  result.push( 
    function() {
      console.log(item + ' ' + list[i]);
    } 
   );
 }
 return result;
}

var fnlist = buildList([1,2,3]);
for (var j = 0; j < fnlist.length; j++) {
  fnlist[j](); 
}

得到的结果:连续输出3个"item3 undefined"

解析:通过执行buildList函数,返回了一个result,那么这个result存放的是3个匿名函数。然而这三个匿名函数其实就是三个闭包,因为它可以访问到父函数的局部变量。所以闭包内的保留的i是最终的值为3.所以list[3]肯定是undefined. item变量值为item3.

改成如下代码:

function buildList(list) {
 var result = [];
 for(var i = 0; i < list.length; i++) {
  var item = 'item' + list[i];
  result.push( 
    (function(i) {
      console.log(item + ' ' + list[i]);
    })(i)
   );
 }
 return result;
}

var fnlist = buildList([1,2,3]);

得到的结果:

item1 1
item2 2
item3 3

解释:这儿虽然传递了一个数组进去,但是返回的是三个自执行的函数。

例4

function newClosure(someNum, someRef) 
{
 var anArray = [1,2,3];
 var num = someNum;
 var ref = someRef;
 return function(x) 
 {
 num += x;
 anArray.push(num);
 console.log('num: ' + num + "; " + 'anArray ' + anArray.toString() + "; " + 'ref.someVar ' + ref.someVar);
 }
}
closure1 = newClosure(40, {someVar: "closure 1"}); 
closure2 = newClosure(1000, {someVar: "closure 2"}); 
closure1(5); // 打印"num: 45; anArray 1,2,3,45; ref.someVar closure 1"
closure2(-10); // 打印"num: 990; anArray 1,2,3,990; ref.someVar closure 2"

每次调用newClosure()都会创建独立的闭包,它们的局部变量num与ref的值并不相同。

例5

function sayAlice() 
{
 var sayAlert = function() { console.log(alice); }
 var alice = 'Hello Alice';
 return sayAlert;
}

var sayAlice2 = sayAlice();
sayAlice2(); // 输出"Hello Alice"

alice变量在sayAlert函数之后定义,这并未影响代码执行。因为返回函数sayAlice2所指向的闭包会包含sayAlice()函数中的所有局部变量,这自然包括了alice变量,因此可以正常打印”Hello Alice”。

例6

function setupSomeGlobals() {
 var num = 666;
 gAlertNumber = function() { console.log(num); }
 gIncreaseNumber = function() { num++; }
 gSetNumber = function(x) { num = x; }
}
setupSomeGlobals();
gAlertNumber(); // 输出666
gIncreaseNumber();
gAlertNumber(); // 输出667
gSetNumber(5);
gAlertNumber(); // 输出5

解释:首先gAlertNumber,gIncreaseNumber,gSetNumber是三个全局变量,并且其三个值都是匿名函数,然而这三个匿名函数本身都是闭包。他们操作的num都是保存在内存中的同一个num,所有会得出上面的结果。

以上这篇通过示例彻底搞懂js闭包就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JSONP 跨域共享信息
Aug 16 Javascript
Node.js事件循环(Event Loop)和线程池详解
Jan 28 Javascript
javascript新闻跑马灯实例代码
Jul 29 Javascript
javascript每日必学之条件分支
Feb 17 Javascript
理解javascript函数式编程中的闭包(closure)
Mar 08 Javascript
深入解析Backbone.js框架的依赖库Underscore.js的作用
May 07 Javascript
微信小程序教程之本地图片上传(leancloud)实例详解
Nov 16 Javascript
bootstrap日历插件datetimepicker使用方法
Dec 14 Javascript
JS+canvas动态绘制饼图的方法示例
Sep 12 Javascript
JS实现读取xml内容并输出到div中的方法示例
Apr 19 Javascript
微信小程序实现日历签到
Sep 21 Javascript
Vue3.0的优化总结
Oct 16 Javascript
用js屏蔽被http劫持的浮动广告实现方法
Aug 10 #Javascript
JS实现下拉菜单列表与登录注册弹窗效果
Aug 10 #Javascript
浅谈sass在vue注意的地方
Aug 10 #Javascript
详解jQuery同步Ajax带来的UI线程阻塞问题及解决办法
Aug 09 #jQuery
Angular 2.0+ 的数据绑定的实现示例
Aug 09 #Javascript
Ionic3实现图片瀑布流布局
Aug 09 #Javascript
JavaScript闭包和回调详解
Aug 09 #Javascript
You might like
过滤掉PHP数组中的重复值的实现代码
2011/07/17 PHP
PHP警告Cannot use a scalar value as an array的解决方法
2012/01/11 PHP
php简单实现数组分页的方法
2016/04/30 PHP
php json_encode与json_decode详解及实例
2016/12/13 PHP
PHP实践教程之过滤、验证、转义与密码详解
2017/07/24 PHP
浅谈PHP发送HTTP请求的几种方式
2017/07/25 PHP
mouse_on_title.js
2006/08/25 Javascript
js 父窗口控制子窗口的行为-打开,关闭,重定位,回复
2010/04/20 Javascript
基于jQuery的的一个隔行变色,鼠标移动变色的小插件
2010/07/06 Javascript
Jquery中find与each方法用法实例
2015/02/04 Javascript
jQuery 遍历函数详解
2015/07/05 Javascript
JS封装cookie操作函数实例(设置、读取、删除)
2015/11/17 Javascript
jquery轮播的实现方式 附完整实例
2016/07/28 Javascript
jQuery中Datatables增加跳转到指定页功能
2017/02/08 Javascript
Vue中的情侣属性$dispatch和$broadcast详解
2019/03/07 Javascript
vue中使用mxgraph的方法实例代码详解
2019/05/17 Javascript
python关闭windows进程的方法
2015/04/18 Python
Python字符串逐字符或逐词反转方法
2015/05/21 Python
python 使用get_argument获取url query参数
2017/04/28 Python
python获取文件真实链接的方法,针对于302返回码
2018/05/14 Python
利用python-pypcap抓取带VLAN标签的数据包方法
2019/07/23 Python
如何基于Python代码实现高精度免费OCR工具
2020/06/18 Python
Pytest测试框架基本使用方法详解
2020/11/25 Python
人力资源管理专业毕业生推荐信
2013/11/07 职场文书
营销总经理的岗位职责
2013/12/15 职场文书
经典优秀毕业生求职信范文分享
2013/12/18 职场文书
电子商务专业学生职业生涯规划
2014/03/07 职场文书
遗产继承公证书
2014/04/09 职场文书
团队拓展活动方案
2014/08/28 职场文书
会计工作态度自我评价
2015/03/06 职场文书
2015年办公室文员工作总结
2015/04/24 职场文书
青年志愿者活动感想
2015/08/07 职场文书
初中政治教学反思
2016/02/23 职场文书
党组织关系的介绍信模板
2019/06/21 职场文书
Python函数中apply、map、applymap的区别
2021/11/27 Python
关于vue-router-link选择样式设置
2022/04/30 Vue.js