通过示例彻底搞懂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 相关文章推荐
JavaScript URL参数读取改进版
Jan 16 Javascript
xml文档转换工具,附图表例子(hta)
Nov 17 Javascript
JavaScript 用Node.js写Shell脚本[译]
Sep 20 Javascript
jQuery筛选器children()案例详解(图文)
Feb 17 Javascript
JavaScript数组去重的3种方法和代码实例
Jul 01 Javascript
JavaScript处理解析JSON数据过程详解
Sep 11 Javascript
JQuery插件Marquee.js实现无缝滚动效果
Apr 26 Javascript
一种基于浏览器的自动小票机打印实现方案(js版)
Jul 26 Javascript
详解vue-cli 构建Vue项目遇到的坑
Aug 30 Javascript
dts文件中删除一个node或属性的操作方法
Aug 05 Javascript
JavaScript创建对象的常用方式总结
Aug 10 Javascript
D3.js的基础部分之数组的处理数组的排序和求值(v3版本)
May 09 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使用ODBC连接数据库的方法
2015/07/18 PHP
PHP CURL或file_get_contents获取网页标题的代码及两者效率的稳定性问题
2015/11/30 PHP
php使用正则表达式获取字符串中的URL
2016/12/29 PHP
PHP ADODB实现分页功能简单示例
2018/05/25 PHP
Z-Blog中用到的js代码
2007/03/15 Javascript
javascript之水平横向滚动歌词同步的应用
2007/05/07 Javascript
JavaScript 动态将数字金额转化为中文大写金额
2009/05/14 Javascript
jquery实现保存已选用户
2014/07/21 Javascript
JavaScript实现俄罗斯方块游戏过程分析及源码分享
2015/03/23 Javascript
JavaScript中SetInterval与setTimeout的用法详解
2015/11/10 Javascript
JavaScript中使用数组方法汇总
2016/02/16 Javascript
js日期插件dateHelp获取本月、三个月、今年的日期
2016/03/07 Javascript
webpack+vue.js快速入门教程
2016/10/12 Javascript
简单实现Vue的observer和watcher
2016/12/21 Javascript
利用vue组件自定义v-model实现一个Tab组件方法示例
2017/12/06 Javascript
AngularJS基于MVC的复杂操作实例讲解
2017/12/31 Javascript
这应该是最详细的响应式系统讲解了
2019/07/22 Javascript
JS实现手写 forEach算法示例
2020/04/29 Javascript
uni-app微信小程序登录授权的实现
2020/05/22 Javascript
vue页面引入three.js实现3d动画场景操作
2020/08/10 Javascript
浅析JavaScript中的事件委托机制跟深浅拷贝
2021/01/20 Javascript
[46:20]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
在Python的Django框架中实现Hacker News的一些功能
2015/04/17 Python
使用SAE部署Python运行环境的教程
2015/05/05 Python
python实时分析日志的一个小脚本分享
2017/05/07 Python
Python Dataframe 指定多列去重、求差集的方法
2018/07/10 Python
python使用threading.Condition交替打印两个字符
2019/05/07 Python
python取余运算符知识点详解
2019/06/27 Python
如何以Winsows Service方式运行JupyterLab
2020/08/30 Python
python爬取天气数据的实例详解
2020/11/20 Python
Pytorch - TORCH.NN.INIT 参数初始化的操作
2021/02/27 Python
个人简历中的自我评价范例
2013/10/29 职场文书
刊首寄语大全
2014/04/11 职场文书
施工安全承诺书
2014/05/22 职场文书
酒店管理求职信
2014/06/09 职场文书
专项法律服务方案
2014/06/11 职场文书