通过示例彻底搞懂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 单击li防止重复加载的实现代码
Dec 24 Javascript
JavaScript关闭当前页面(窗口)不带任何提示
Mar 26 Javascript
详解Js模板引擎(TrimPath)
Nov 22 Javascript
用director.js实现前端路由使用实例
Jan 27 Javascript
jQuery动态生成不规则表格(前后端)
Feb 21 Javascript
JS检测数组类型的方法小结
Mar 14 Javascript
详解用Node.js实现Restful风格webservice
Sep 29 Javascript
微信小程序实现YDUI的ScrollNav组件
Feb 02 Javascript
JavaScript中click和onclick本质区别与用法分析
Jun 07 Javascript
如何解决webpack-dev-server代理常切换问题
Jan 09 Javascript
Vue动态修改网页标题的方法及遇到问题
Jun 09 Javascript
基于Node.js搭建hexo博客过程详解
Jun 25 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
解决FastCGI 进程超过了配置的活动超时时限的问题
2013/07/03 PHP
浅谈php正则表达式中的非贪婪模式匹配的使用
2014/11/25 PHP
解决PHP里大量数据循环时内存耗尽的方法
2015/10/10 PHP
php读取torrent种子文件内容的方法(测试可用)
2016/05/03 PHP
Laravel日志用法详解
2016/10/09 PHP
微信第三方登录(原生)demo【必看篇】
2017/05/26 PHP
PDO::getAttribute讲解
2019/01/28 PHP
一次因composer错误使用引发的问题与解决
2019/03/06 PHP
JavaScript 无符号右移运算符
2009/04/17 Javascript
jquery中获取select选中值的代码
2011/06/27 Javascript
鼠标焦点离开文本框时验证的js代码
2013/07/19 Javascript
BootStrap的弹出框(Popover)支持鼠标移到弹出层上弹窗层不隐藏的原因及解决办法
2016/04/03 Javascript
JavaScript构建自己的对象示例
2016/11/29 Javascript
Bootstrap面板使用方法
2017/01/16 Javascript
详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)
2017/08/30 Javascript
node-sass安装失败的原因与解决方法
2017/09/04 Javascript
详解JavaScript基础知识(JSON、Function对象、原型、引用类型)
2018/01/16 Javascript
你点的 ES6一些小技巧,请查收
2018/04/25 Javascript
Javascript call及apply应用场景及实例
2020/08/26 Javascript
Nuxt.js nuxt-link与router-link的区别说明
2020/11/06 Javascript
浅谈tensorflow中几个随机函数的用法
2018/07/27 Python
Python Django给admin添加Action的方法实例详解
2019/04/29 Python
Python使用Pandas库实现MySQL数据库的读写
2019/07/06 Python
python处理大日志文件
2019/07/23 Python
Django models文件模型变更错误解决
2020/05/11 Python
解决tensorflow/keras时出现数组维度不匹配问题
2020/06/29 Python
Python根据字符串调用函数过程解析
2020/11/05 Python
施华洛世奇德国官网:SWAROVSKI德国
2017/02/01 全球购物
SIMON MILLER官网:洛杉矶的生活方式品牌
2020/10/19 全球购物
大学生简历中个人的自我评价
2013/10/06 职场文书
应届行政管理专业个人自我评价
2013/12/28 职场文书
大学军训感言300字
2014/03/09 职场文书
质量整改报告范文
2014/11/08 职场文书
html+css 实现简易导航栏功能
2021/04/07 HTML / CSS
python神经网络编程之手写数字识别
2021/05/08 Python
java高级用法JNA强大的Memory和Pointer
2022/04/19 Java/Android