通过示例彻底搞懂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 动态改变图片大小
Jun 11 Javascript
javascript与CSS复习(《精通javascript》)
Jun 29 Javascript
在VS2008中使用jQuery智能感应的方法
Dec 30 Javascript
jQuery实现的自定义弹出层效果实例详解
Sep 04 Javascript
jQuery下拉菜单的实现代码
Nov 03 Javascript
利用Js的console对象,在控制台打印调式信息测试Js的实现
Nov 26 Javascript
js封装tab标签页实例分享
Dec 19 Javascript
React Native悬浮按钮组件的示例代码
Apr 05 Javascript
JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】
May 07 Javascript
JavaScript 正则命名分组【推荐】
Jun 07 Javascript
Vue请求java服务端并返回数据代码实例
Nov 28 Javascript
JS的时间格式化和时间戳转换函数示例详解
Jul 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常用函数的用法详解
2013/05/10 PHP
php实现将任意进制数转换成10进制的方法
2015/04/17 PHP
JQuery 浮动导航栏实现代码
2009/08/27 Javascript
javascript事件问题
2009/09/05 Javascript
jquery删除指定的html标签并保留标签内文本内容的方法
2014/04/02 Javascript
AngularJS+Node.js实现在线聊天室
2015/08/28 Javascript
jquery在ie7下选择器的问题导致append失效的解决方法
2016/01/10 Javascript
Vue.js实现简单ToDoList 前期准备(一)
2016/12/01 Javascript
超全面的vue.js使用总结
2017/02/12 Javascript
JavaScript仿微信打飞机游戏
2020/07/05 Javascript
js实现放大镜特效
2017/05/18 Javascript
浅析微信小程序modal弹窗关闭默认会执行cancel问题
2019/10/14 Javascript
JS控制只能输入数字并且最多允许小数点两位
2019/11/24 Javascript
浅谈element中InfiniteScroll按需引入的一点注意事项
2020/06/05 Javascript
PHP 502bad gateway原因及解决方案
2020/11/13 Javascript
Vant+postcss-pxtorem 实现浏览器适配功能
2021/02/05 Javascript
Python如何快速上手? 快速掌握一门新语言的方法
2017/11/14 Python
python远程连接服务器MySQL数据库
2018/07/02 Python
nginx黑名单和django限速,最简单的防恶意请求方法分享
2019/08/09 Python
python基于plotly实现画饼状图代码实例
2019/12/16 Python
PyCharm使用之配置SSH Interpreter的方法步骤
2019/12/26 Python
pytorch实现建立自己的数据集(以mnist为例)
2020/01/18 Python
详解Python中namedtuple的使用
2020/04/27 Python
通过HTML5规范搞定i、em、b、strong元素的区别
2017/03/04 HTML / CSS
HTML5中外部浏览器唤起微信分享
2020/01/02 HTML / CSS
德国化妆品和天然化妆品网上商店:kosmetikfuchs.de
2017/06/09 全球购物
Java面试题:为什么要用Java
2012/05/11 面试题
电大学习个人自我评价范文
2013/10/04 职场文书
综合办公室个人的自我评价
2013/12/22 职场文书
市三好学生主要事迹
2014/01/28 职场文书
企业安全生产承诺书
2014/05/22 职场文书
论群众路线学习笔记
2014/11/06 职场文书
辩论会主持词
2015/07/03 职场文书
初中物理教学反思
2016/02/19 职场文书
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
2021/05/21 Redis
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis