通过示例彻底搞懂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 相关文章推荐
分享XmlHttpRequest调用Webservice的一点心得
Jul 20 Javascript
js字符串转换成xml对象并使用技巧解读
Apr 18 Javascript
JavaScript 判断用户输入的邮箱及手机格式是否正确
Dec 08 Javascript
javascript操作referer详细解析
Mar 10 Javascript
javascript中的括号()用法小结
Apr 14 Javascript
Jsonp post 跨域方案
Jul 06 Javascript
Javascript oop设计模式 面向对象编程简单实例介绍
Dec 13 Javascript
node.js请求HTTPS报错:UNABLE_TO_VERIFY_LEAF_SIGNATURE\的解决方法
Dec 18 Javascript
在原生不支持的旧环境中添加兼容的Object.keys实现方法
Sep 11 Javascript
JavaScript实现一个带AI的井字棋游戏源码
May 21 Javascript
解决vue自定义全局消息框组件问题
Nov 22 Javascript
jQuery实现中奖播报功能(让文本滚动起来) 简单设置数值即可
Mar 20 jQuery
用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
easyui的tabs update正确用法分享
2014/03/21 PHP
php实现将base64格式图片保存在指定目录的方法
2016/10/13 PHP
浅谈PHP各环境下的伪静态配置
2019/03/13 PHP
Jquery封装tab自动切换效果的具体实现
2013/07/13 Javascript
jQuery简易图片放大特效示例代码
2014/06/09 Javascript
JavaScript 函数的执行过程
2016/05/09 Javascript
BootStrap轮播HTML代码(推荐)
2016/12/10 Javascript
Angular.js基础学习之初始化
2017/03/10 Javascript
通过vue-router懒加载解决首次加载时资源过多导致的速度缓慢问题
2018/04/08 Javascript
Vue+axios实现统一接口管理的方法
2018/07/23 Javascript
浏览器事件循环与vue nextTicket的实现
2019/04/16 Javascript
JS工厂模式开发实践案例分析
2019/10/17 Javascript
vue 自定义右键样式的实例代码
2019/11/06 Javascript
[01:06:54]DOTA2-DPC中国联赛 正赛 RNG vs Dragon BO3 第一场 1月24日
2021/03/11 DOTA
python判断端口是否打开的实现代码
2013/02/10 Python
Python中文字符串截取问题
2015/06/15 Python
Python的Django框架中模板碎片缓存简介
2015/07/24 Python
使用Python写CUDA程序的方法
2017/03/27 Python
基于python中staticmethod和classmethod的区别(详解)
2017/10/24 Python
Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法
2018/01/11 Python
Django如何实现上传图片功能
2019/08/16 Python
python求加权平均值的实例(附纯python写法)
2019/08/22 Python
python迭代器常见用法实例分析
2019/11/22 Python
Python hmac模块使用实例解析
2019/12/24 Python
Python字符串hashlib加密模块使用案例
2020/03/10 Python
python 连续不等式语法糖实例
2020/04/15 Python
Django form表单与请求的生命周期步骤详解
2020/06/07 Python
python Scrapy框架原理解析
2021/01/04 Python
世界最大的票务市场:viagogo
2017/02/16 全球购物
2013年高中生自我评价
2013/10/23 职场文书
财务科科长岗位职责
2014/03/10 职场文书
教师党员公开承诺事项
2014/05/28 职场文书
学习十八届四中全会依法治国心得体会
2014/11/03 职场文书
保管员岗位职责
2015/02/14 职场文书
地心历险记观后感
2015/06/15 职场文书
Python将CSV文件转化为HTML文件的操作方法
2021/06/30 Python