通过示例彻底搞懂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 相关文章推荐
用脚本调用样式的几种方法
Dec 09 Javascript
ExtJS 2.0实用简明教程 之Border区域布局
Apr 29 Javascript
jQuery操作 input type=checkbox的实现代码
Jun 14 Javascript
jquery通过a标签删除table中的一行的代码
Dec 02 Javascript
深入理解JavaScript内置函数
Jun 03 Javascript
浅谈Cookie的生命周期问题
Aug 02 Javascript
深入理解vue.js中$watch的oldvalue与newValue
Aug 07 Javascript
Vue使用Clipboard.JS在h5页面中复制内容实例详解
Sep 03 Javascript
vue-父子组件和ref实例详解
Nov 10 Javascript
KnockoutJS数组比较算法实例详解
Nov 25 Javascript
微信小程序实现选择地址省市区三级联动
Jun 21 Javascript
vue绑定数字类型 value为数字的实例
Aug 31 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 extract 将数组拆分成多个变量的函数
2010/06/30 PHP
php下使用iconv需要注意的问题
2010/11/20 PHP
PHP面向对象程序设计之接口用法
2014/08/20 PHP
php常用字符串比较函数实例汇总
2014/11/24 PHP
PHP中数据类型转换的三种方式
2015/04/02 PHP
PHP使用观察者模式处理异常信息的方法详解
2019/09/24 PHP
jQuery Masonry瀑布流插件使用详解
2014/11/17 Javascript
javascript抽象工厂模式详细说明
2014/12/16 Javascript
js实现显示当前状态的导航效果代码
2015/08/28 Javascript
fastclick插件导致日期(input[type=&quot;date&quot;])控件无法被触发该如何解决
2015/11/09 Javascript
快速解决js开发下拉框中blur与click冲突
2016/10/10 Javascript
js仿手机页面文件下拉刷新效果
2016/10/14 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
2016/10/25 Javascript
angularJS深拷贝详解
2017/03/23 Javascript
vue实现todolist单页面应用
2017/04/11 Javascript
webpack4与babel配合使es6代码可运行于低版本浏览器的方法
2018/10/12 Javascript
JavaScript中concat复制数组方法浅析
2019/01/20 Javascript
python之模拟鼠标键盘动作具体实现
2013/12/30 Python
python万年历实现代码 含运行结果
2017/05/20 Python
基于pandas数据样本行列选取的方法
2018/04/20 Python
用python统计代码行的示例(包括空行和注释)
2018/07/24 Python
Django 视图层(view)的使用
2018/11/09 Python
对Python3中dict.keys()转换成list类型的方法详解
2019/02/03 Python
python打包成so文件过程解析
2019/09/28 Python
Python日志器使用方法及原理解析
2020/09/27 Python
Asics日本官网:鬼冢八喜郎创立的跑鞋运动品牌
2017/10/18 全球购物
澳大利亚拥有最好的家具和家居用品在线目的地:Nestz
2019/02/23 全球购物
职业生涯规划怎么写
2013/12/29 职场文书
商务会议邀请函
2014/01/09 职场文书
企业管理毕业生求职信范文
2014/03/07 职场文书
成都人事代理协议书
2014/10/25 职场文书
公务员检讨书
2014/11/01 职场文书
世界水日宣传活动总结
2015/02/09 职场文书
停水通知
2015/04/16 职场文书
婚礼双方父亲致辞
2015/07/27 职场文书
HTML+CSS+JS实现图片的瀑布流布局的示例代码
2021/04/22 HTML / CSS