通过示例彻底搞懂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 相关文章推荐
javascript 写类方式之三
Jul 05 Javascript
JS性能优化笔记搜索整理
Aug 21 Javascript
javascript的switch用法注意事项分析
Feb 02 Javascript
js鼠标点击按钮切换图片-图片自动切换-点击左右按钮切换特效代码
Sep 02 Javascript
JS根据浏览器窗口大小实时动态改变网页文字大小的方法
Feb 25 Javascript
jstl中判断list中是否包含某个值的简单方法
Oct 14 Javascript
折叠菜单及选择器的运用
Feb 03 Javascript
用angular实现多选按钮的全选与反选实例代码
May 23 Javascript
javascript原生封装一个淡入淡出效果的函数测试实例代码
Mar 19 Javascript
layui问题之模拟select点击事件的实例讲解
Aug 15 Javascript
vue element upload实现图片本地预览
Aug 20 Javascript
小程序选项卡以及swiper套用(跨页面)
Jun 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 addslashes和mysql_real_escape_string
2010/01/24 PHP
php获取字符串中各个字符出现次数的方法
2015/02/23 PHP
Laravel向公共模板赋值方法总结
2019/06/25 PHP
jQuery 的全选(全非选)即取得被选中的值使用介绍
2013/11/12 Javascript
node.js中的fs.lstatSync方法使用说明
2014/12/16 Javascript
JS实现两表格里数据来回转移的方法
2015/05/28 Javascript
jQuery实现向下滑出的二级菜单效果实例
2015/08/22 Javascript
javascript实现保留两位小数的多种方法
2015/12/18 Javascript
JavaScript实现省市县三级级联特效
2017/05/16 Javascript
angular中实现li或者某个元素点击变色的两种方法
2017/07/27 Javascript
使用FileReader API创建Vue文件阅读器组件
2018/04/03 Javascript
vue项目webpack中Npm传递参数配置不同域名接口
2018/06/15 Javascript
解决vue2.0路由跳转未匹配相应用路由避免出现空白页面的问题
2018/08/24 Javascript
Vue3.0 响应式系统源码逐行分析讲解
2019/10/14 Javascript
vue实现短信验证码输入框
2020/04/17 Javascript
[07:31]DOTA2卡尔工作室 英雄介绍主宰篇
2013/06/25 DOTA
python抓取豆瓣图片并自动保存示例学习
2014/01/10 Python
python中的内置函数max()和min()及mas()函数的高级用法
2018/03/29 Python
python中ASCII码字符与int之间的转换方法
2018/07/09 Python
Python读取excel指定列生成指定sql脚本的方法
2018/11/28 Python
python实现桌面壁纸切换功能
2019/01/21 Python
Python3实现统计单词表中每个字母出现频率的方法示例
2019/01/28 Python
python 多线程串行和并行的实例
2019/02/22 Python
python绘制漏斗图步骤详解
2019/03/04 Python
Python实现的对一个数进行因式分解操作示例
2019/06/27 Python
Python基于BeautifulSoup爬取京东商品信息
2020/06/01 Python
Python异常处理机制结构实例解析
2020/07/23 Python
python实现启动一个外部程序,并且不阻塞当前进程
2020/12/05 Python
平面设计师工作职责范文
2013/12/03 职场文书
党支部公开承诺践诺书
2014/03/28 职场文书
小学重阳节活动总结
2015/03/24 职场文书
冬季作息时间调整通知
2015/04/24 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
Python Pandas数据分析之iloc和loc的用法详解
2021/11/11 Python
python实现会员信息管理系统(List)
2022/03/18 Python
MySQL transaction事务安全示例讲解
2022/06/21 MySQL