通过示例彻底搞懂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 相关文章推荐
jQuery实现瀑布流布局
Dec 12 Javascript
jQuery扁平化风格下拉框美化插件FancySelect使用指南
Feb 10 Javascript
jQuery实现别踩白块儿网页版小游戏
Jan 18 Javascript
JS仿JQuery选择器功能
Mar 08 Javascript
JS中关于正则的巧妙操作
Aug 31 Javascript
不得不知的ES6小技巧
Jul 28 Javascript
Canvas实现微信红包照片效果
Aug 21 Javascript
vue+element表格导出为Excel文件
Sep 26 Javascript
vue.js的简单自动求和计算实例
Nov 08 Javascript
JS实现轮播图效果
Jan 11 Javascript
vue-以文件流-blob-的形式-下载-导出文件操作
Aug 07 Javascript
js实现QQ邮箱邮件拖拽删除功能
Aug 27 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根据生日计算年龄的方法
2015/07/13 PHP
php微信公众平台配置接口开发程序
2016/09/22 PHP
ext 代码生成器
2009/08/07 Javascript
javascript jscroll模拟html元素滚动条
2012/12/18 Javascript
js创建子窗口并且回传值示例代码
2013/07/02 Javascript
jQuery+ajax实现鼠标单击修改内容的思路
2014/06/29 Javascript
js数组与字符串的相互转换方法
2014/07/09 Javascript
javascript删除一个html元素节点的方法
2014/12/20 Javascript
js实现(全选)多选按钮的方法【附实例】
2016/03/30 Javascript
浅析JavaScript中浏览器的兼容问题
2016/04/19 Javascript
jquery自定义插件结合baiduTemplate.js实现异步刷新(附源码)
2016/12/22 Javascript
原生Aajax 和jQuery Ajax 写法个人总结
2017/03/24 jQuery
Express框架之connect-flash详解
2017/05/31 Javascript
JS仿QQ好友列表展开、收缩功能(第一篇)
2017/07/07 Javascript
Vue组件之全局组件与局部组件的使用详解
2017/10/09 Javascript
vue-cli脚手架的安装教程图解
2018/09/02 Javascript
vue ssr 实现方式(学习笔记)
2019/01/18 Javascript
ios中视频的最后一桢问题解决
2019/05/14 Javascript
JS实现简易图片自动轮播
2020/10/16 Javascript
用python实现的线程池实例代码
2018/01/06 Python
解决Python requests库编码 socks5代理的问题
2018/05/07 Python
Python实现将Excel转换成xml的方法示例
2018/08/25 Python
Python json模块dumps、loads操作示例
2018/09/06 Python
在Pandas中给多层索引降级的方法
2018/11/16 Python
Python 监测文件是否更新的方法
2019/06/10 Python
世界著名的顶级牛排:Omaha Steak(奥马哈牛排)
2016/09/20 全球购物
Melijoe英国官网:法国儿童时尚网站
2016/11/18 全球购物
彪马美国官网:PUMA美国
2017/03/09 全球购物
Sunglasses Shop瑞典:欧洲领先的太阳镜网上商店
2018/04/22 全球购物
介绍一下SQL Server里面的索引视图
2016/07/31 面试题
大学班级干部的自我评价分享
2014/02/10 职场文书
好书伴我成长演讲稿
2014/05/14 职场文书
幽默自我介绍演讲稿
2014/08/21 职场文书
教师节学生演讲稿
2014/09/03 职场文书
归途列车观后感
2015/06/17 职场文书
运动会致辞稿
2015/07/29 职场文书