通过示例彻底搞懂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 相关文章推荐
[JS]点出统计器
Oct 11 Javascript
JavaScript CSS修改学习第五章 给“上传”添加样式
Feb 19 Javascript
jQuery Ajax使用 全解析
Dec 15 Javascript
基于pthread_create,readlink,getpid等函数的学习与总结
Jul 17 Javascript
javascript firefox 自动加载iframe 自动调整高宽示例
Aug 27 Javascript
推荐8款jQuery轻量级树形Tree插件
Nov 12 Javascript
使用JavaScript 编写简单计算器
Nov 24 Javascript
JavaScript实现上下浮动的窗口效果代码
Oct 12 Javascript
Google 地图获取API Key详细教程
Aug 06 Javascript
JS实现禁止鼠标右键的功能
Oct 15 Javascript
JavaScript设计模式之模板方法模式原理与用法示例
Aug 07 Javascript
vue插件--仿微信小程序showModel实现模态提示窗功能
Aug 19 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/26 PHP
TP5框架实现自定义分页样式的方法示例
2020/04/05 PHP
JavaScript类和继承 constructor属性
2010/03/04 Javascript
常用jQuery选择器总结
2014/07/11 Javascript
Javascript让DEDECMS告别手写Tag
2014/09/01 Javascript
JavaScript中操作Mysql数据库实例
2015/04/02 Javascript
jQuery在线选座位插件seat-charts特效代码分享
2015/08/27 Javascript
JS实现的颜色实时渐变效果完整实例
2016/03/25 Javascript
AngularJS实现数据列表的增加、删除和上移下移等功能实例
2016/09/05 Javascript
使用travis-ci如何持续部署node.js应用详解
2017/07/30 Javascript
vue 实现在函数中触发路由跳转的示例
2018/09/01 Javascript
详解vue 动态加载并注册组件且通过 render动态创建该组件
2019/05/30 Javascript
浅谈layui数据表格判断问题(加入表单元素),设置单元格样式
2019/10/26 Javascript
iview实现图片上传功能
2020/06/29 Javascript
编写Python脚本来实现最简单的FTP下载的教程
2015/05/04 Python
Django中对数据查询结果进行排序的方法
2015/07/17 Python
一张图带我们入门Python基础教程
2017/02/05 Python
python中nan与inf转为特定数字方法示例
2017/05/11 Python
python实现图片筛选程序
2018/10/24 Python
Django使用中间件解决前后端同源策略问题
2019/09/02 Python
如何打包Python Web项目实现免安装一键启动的方法
2020/05/21 Python
Numpy中ndim、shape、dtype、astype的用法详解
2020/06/14 Python
Pycharm打开已有项目配置python环境的方法
2020/07/03 Python
世界上第一个水枕头:Mediflow
2018/12/06 全球购物
斯图尔特·韦茨曼鞋加拿大官网:Stuart Weitzman加拿大
2019/10/13 全球购物
软件测试工程师面试问题精选
2016/10/28 面试题
预备党员转正思想汇报
2014/01/12 职场文书
乡镇安全生产目标责任书
2014/07/23 职场文书
教师节学生演讲稿
2014/09/03 职场文书
教师文明餐桌光盘行动倡议书
2015/04/28 职场文书
小学数学教学反思范文
2016/02/16 职场文书
《当代神农氏》教学反思
2016/02/23 职场文书
Mysql实现主从配置和多主多从配置
2021/06/02 MySQL
MySQL系列之十五 MySQL常用配置和性能压力测试
2021/07/02 MySQL
Java实现房屋出租系统详解
2021/10/05 Java/Android
苹果电脑mac os中货币符号快捷输入
2022/02/17 杂记