通过示例彻底搞懂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操作select控件的几种方法
Jun 02 Javascript
js对象的比较
Feb 26 Javascript
jquery 动态创建元素的方式介绍及应用
Apr 21 Javascript
javascript实现动态侧边栏代码
Feb 19 Javascript
JavaScript实现节点的删除与序号重建实例
Aug 05 Javascript
JS实现来回出现文字的状态栏特效代码
Oct 31 Javascript
bootstrap选项卡扩展功能详解
Jun 14 Javascript
js es6系列教程 - 基于new.target属性与es5改造es6的类语法
Sep 02 Javascript
详解vuex状态管理模式
Nov 01 Javascript
详解js中的原型,原型对象,原型链
Jul 16 Javascript
JS实现4位随机验证码
Oct 19 Javascript
js实现碰撞检测
Jan 29 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
PHILIPS AE3805收音机的分析打磨
2021/03/02 无线电
phpmyadmin安装时提示:Warning: require_once(./libraries/common.inc.php)错误解决办法
2011/08/18 PHP
使用PHP导出Redis数据到另一个Redis中的代码
2014/03/12 PHP
PHP使用array_multisort对多个数组或多维数组进行排序
2014/12/16 PHP
php提示Failed to write session data错误的解决方法
2014/12/17 PHP
PHP命令行执行整合pathinfo模拟定时任务实例
2016/08/12 PHP
PHP实现递归目录的5种方法
2016/10/27 PHP
自写的利用PDO对mysql数据库增删改查操作类
2018/02/19 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
基于javascript滚动图片具体实现
2013/11/18 Javascript
jQuery的each终止或跳过示例代码
2013/12/12 Javascript
javascript监听鼠标滚轮事件浅析
2014/06/05 Javascript
基于jquery ui的alert,confirm方案(支持换肤)
2015/04/03 Javascript
javascript通过元素id和name直接取得元素的方法
2015/04/28 Javascript
浅谈Javascript线程及定时机制
2015/07/02 Javascript
Vue.JS入门教程之自定义指令
2016/12/08 Javascript
jq给页面添加覆盖层遮罩的实例
2017/02/16 Javascript
javascript完美实现给定日期返回上月日期的方法
2017/06/15 Javascript
js实现上传并压缩图片效果
2018/01/10 Javascript
nodejs读取并去重excel文件
2018/04/22 NodeJs
详解Vue 多级组件透传新方法provide/inject
2018/05/09 Javascript
解决JavaScript layui 下拉框不显示的问题
2018/08/14 Javascript
jquery的$().each和$.each的区别
2019/01/18 jQuery
nodejs dgram模块广播+组播的实现示例
2019/11/04 NodeJs
微信小程序复选框实现多选一功能过程解析
2020/02/14 Javascript
python使用点操作符访问字典(dict)数据的方法
2015/03/16 Python
Python实现爬取逐浪小说的方法
2015/07/07 Python
python SMTP实现发送带附件电子邮件
2018/05/22 Python
Python Numpy 自然数填充数组的实现
2019/11/28 Python
Python logging日志模块 配置文件方式
2020/07/12 Python
英国最大的在线时尚眼镜店:Eyewearbrands
2019/03/12 全球购物
Coccinelle官网:意大利的著名皮具品牌
2019/05/15 全球购物
幼儿如何来做好自我评价
2013/11/05 职场文书
财务情况说明书范文
2014/05/06 职场文书
英语投诉信范文
2015/07/03 职场文书
Python中time与datetime模块使用方法详解
2022/03/31 Python