好程序员前端教程之JavaScript闭包和匿名函数的关系详解
本文讲的是关于JavaScript闭包和匿名函数两者之间的关系,从匿名函数概念到立即执行函数,最后到闭包。下面一起来看看文章分析,希望你会喜欢。
前面讲了一篇在for循环中加setTimeout输出内容,我们用到了一个闭包,但同时也可以说是匿名函数,到底匿名函数和闭包有没有关系呢?【答案是它们之间没有关系】
匿名函数
匿名函数,顾名思义,就是没有名字的函数,与之对应的就是有名字的函数,也叫具名函数。
//匿名函数
function (){

console.log('匿名函数');

}
//具名函数
function myFn(){

console.log('具名函数');

}
//变量a就是匿名函数的名字
var a = function(){

console.log('a就是匿名函数的名字');

}
如果我们直接在控制台中运行匿名函数,会发现报错,无法执行。匿名函数是无法执行的,一般用到匿名函数的时候都是立即执行,也叫自执行匿名函数或者自调用匿名函数,一般人都叫立即执行函数。
立即执行函数
比较常见的立即执行函数如下:
;(function(){

console.log('caibaojian.com');

})()

;(function(){

console.log('caibaojian.com');

}());
上面这两种都是典型的立即执行函数写法,两者的区分就是一个执行在匿名函数括号外面,另外一个发起执行的括号在匿名函数里面。比较常见的是第一种写法,括号在匿名函数的括号外面。
步骤分解:
1.首先声明一个匿名函数 function(){alert('我是匿名函数')}。
2.然后在匿名函数后面接一对括号 (),调用这个匿名函数。
那为什么还要用一个括号包起来呢?其实是为了兼容JS的语法,如果我们不加括号,直接写成
function (){alert('我是匿名函数')}()
浏览器会报语法错误,想要通过浏览器的语法检查,必须加点小东西,比如下面几种
(function(){alert('我是匿名函数')} ()) // 用括号把整个表达式包起来
(function(){alert('我是匿名函数')}) () //用括号把函数包起来
!function(){alert('我是匿名函数')}() // 求反,我们不在意值是多少,只想通过语法检查。
+function(){alert('我是匿名函数')}()
-function(){alert('我是匿名函数')}()
~function(){alert('我是匿名函数')}()
void function(){alert('我是匿名函数')}()
new function(){alert('我是匿名函数')}()
实际上,立即执行函数的作用只有一个:创建一个独立的作用域,在这个作用域里面,外面访问不到,避免变量污染。比如我们前面的一篇文章,setTimeout的第三个参数里面讲到的一道题目。
for(var i=0;i<6;i++){

setTimeout(function(){console.log(i); //为什么输出的总是 6,而不是0,1,2,3,4,5
},i*1000);

}
我们发现上面这个定时器总是输出6,因为setTimeout里面的执行函数是异步的,执行的时候,i的值是贯穿整个作用域的,而不是单独一个给每个定期器分配了一个i,for运行完的值是6,此时输出就总是6了。
那怎么解决呢?用立即执行函数给每个定时器创造一个独立作用域即可。
for(var i=0;i<6;i++){

(function(j){setTimeout(function(){console.log(j);},j*1000);
})(i);  

}
在for循环执行时,立即执行函数就已经有了结果了。而每个立即执行函数里面的j值就是独立的一个,不会受后面影响。所以会分别执行5次定时器。
//第一个立即执行函数
(function(0){

setTimeout(function(){console.log(0);
})

})(0);
//第二个立即执行函数
(function(1){

setTimeout(function(){console.log(1);
})

})(1);
//……
//第六个立即执行函数
(function(5){

setTimeout(function(){console.log(5);
})

})(5);

i 的值从 0 变化到 5,对应 6 个立即执行函数,这 6 个立即执行函数里面的 j 「分别」是 0、1、2、3、4、5。
上面说了这么多关于匿名函数和立即执行函数的,相信你对这两个概念已经很清楚,那么闭包跟匿名函数有关系吗?
闭包
js闭包是指有权访问另一个函数作用域中的变量的函数,个人认为js闭包最大的用处就是防止对全局作用域的污染。闭包最神奇的地方就是能在一个函数外访问函数中的局部变量,把这些变量用闭包的形式放在函数中便能避免污染。
我们可以分离出上面的第一个立即执行函数
function box(i){

setTimeout(function(){console.log(i);
},i*1000);

}
box(1);

//或者这样
function box(i){

function inner(){console.log(i);
}
return inner;

}
var outer = box(1);
outer();
结论
很明显这是一个闭包,然后我们再看看我们最前面的匿名函数代码和立即执行函数代码,可以看出匿名函数和闭包两者并没有关系。闭包既可以在匿名函数也可以在具名函数中使用。
这个for循环中的闭包怎么理解以及自执行匿名函数的作用:
这个for循环产生的闭包其实是定时器的回调函数,这些回调函数的执行环境是window,类似刚才例子中的引用inner的全局outer的执行环境,匿名函数则相当于刚才例子中的box函数。
Stackoverflow网站上的一个提问跟我们今天分析的类似。有一个回答挺好。
闭包机制适用于所有JavaScript函数,无论是否匿名。
我认为这两个概念之间的混淆来自于使用术语“闭包”,其中作者已经说过“下面的代码创建一个闭包”,然后给出了一个恰好使用匿名函数的例子。 在这种情况下,闭包机制通常是使特定代码段按预期工作的重要因素,而使用匿名函数而不是命名函数恰好是编码它的便捷方式。 阅读这些例子并且第一次看到“闭包”的人然后误解了这个术语,并继续在他们自己的Stack Overflow或博客文章中错误地使用它,因此混乱传播。
一开始我以为匿名函数跟闭包有关系,那是因为恰好这个定时器使用了闭包和匿名函数,让我们误认为两者之间有关系,其实还有很多种方法可以解决这个问题,比如我们之前说到的setTimeout的第三个参数,同样可以得到跟使用立即执行函数同样的效果。
所以说匿名函数和闭包之间没有什么关系,只不过很多时候在用到匿名函数解决问题的时候恰好形成了一个闭包,就导致很多人分不清楚匿名函数和闭包的关系。

好程序员前端教程之JavaScript闭包和匿名函数的关系详解...相关推荐

  1. javascript技术教程蔡敏_程序员都必掌握的前端教程之JavaScript基础教程(上)

    阅读本文约需要10分钟,您可以先关注我们,避免下次无法找到. 本篇文章成哥继续带大家来学习前端教程之JavaScript,网页的动态事件基本上都是靠它来实现的.下面我们就一起来学习内容吧! 01 Ja ...

  2. 从Java程序员进阶到架构师,6大核心技能要领详解

    " java架构师技能将分为如下6大环节:数据结构和算法,Java高级特性,Java web核心,数据库,Java框架与必备工具,系统架构设计. 希望能真正帮助到从程序员进阶到架构师之路的朋 ...

  3. web前端教程之JavaScript的作用域

    作为一个前端工程师,你必须对JavaScript的作用域不陌生,传统常见的有函数级作用域,还有全局作用域,ES6 let const 的块级作用域,其实还有一个你不知道的块级作用域,今天小千就来给大家 ...

  4. Java程序员进阶必读,最全微服务架构技术点详解来啦

    前言 微服务作为这个互联网时代最火的技术之一,想必大家即使没有学习过也有所了解,它提倡将单一应用程序划分成一组小的服务,服务之间相互协调.互相配合,为用户提供最终价值.每个服务运行在其独立的进程中,服 ...

  5. C++后端程序员必须彻底搞懂Nginx,从原理到实战详解

    本文首先介绍 Nginx 的反向代理.负载均衡.动静分离和高可用的原理,随后详解 Nginx 的配置文件,最后通过实际案例实现 Nginx 反向代理和负载均衡的具体配置.学会 Nginx ,一篇足够了 ...

  6. web程序前后台功能实现_好程序员web前端教程之JS继承实现方式解析

    好程序员web前端教程之JS继承实现方式解析,JS是Web前端三要素之一,也是每一个初学前端的同学遭遇的第一条拦路虎.很多人反应JS学习不易,各类知识点概念及应用常常让人抓耳挠腮.在接下来的北京Web ...

  7. 【前端系列教程之JavaScript】01_JavaScript概述和引入方式

    JavaScript概述 JavaScript可以做什么 页面的各种动画效果 页面的点击/移入响应 对客户端数据进行验证 各种页面小游戏 用途总结 嵌入动态文本于HTML页面. 对浏览器事件做出响应( ...

  8. 黑马程序员前端培训:高效的前端编程入门训练方法

    如今,"前端"这个词已经成为一个大方向的概念,其涵盖的范围可以说非常广:比如浏览器的网页开发.移动App开发.桌面应用开发等等.但是,立足到每一个具体的问题上,前端开发都需要使用到 ...

  9. 好程序员Java教程分享JavaScript面试问题及答案(一)

    好程序员Java教程分享JavaScript面试问题及答案(一) 1.使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?如何避免这个 ...

最新文章

  1. 详细分析本机号码一键登录原理
  2. 节能信标组比赛过程中直流电源设置
  3. 【采用】干货请收好:终于有人把用户画像的流程、方法讲明白了
  4. oracle表重命名 索引,CSS_在Oracle数据库中按用户名重建索引的方法,如果你管理的Oracle数据库下某 - phpStudy...
  5. win10 如何锁定计算机,Win10 1909 专业版怎么锁定计算机屏幕
  6. 计算机名称 steam,Steam电脑配置排名:前19名都是N卡
  7. python新手难点_汇总初学python时的28个操作难点(新手必看篇)
  8. 运行python manage.py runserver报错现象、原因和解决办法
  9. Ke模拟器kemulator 1.0 绿色中文版
  10. 优秀课程案例:使用Scratch制作水果忍者游戏!
  11. 【UE4笔记】Collision碰撞
  12. Android Studio历史版本
  13. iOS开发实例 | Demo:数独小游戏
  14. 宁录哨兵机器人_当天启碰上哨兵机器人孰强孰弱?这部漫画给出了答案!
  15. 那些令人发燥的JAVA虚引用
  16. C语言动态规划和文件操作练习——通讯录
  17. win10系统找不到telnet服务器,win10系统找不到Telnet服务的解决教程
  18. C语言趣味一百道 第25题 2017_12_24
  19. 详解注意力机制和Transformer
  20. HQChart使用教程11-如何把K线数据API替换成自己的API数据

热门文章

  1. Dubbo底层采用Socket进行通信详解
  2. 怎么把东西去掉修图_很多人花几千块学习商业修图,其实跟把钱扔了一样。?...
  3. 详解TCP协议三次握手四次挥手
  4. android 使用动态的svg资源,在Android中使用SVG作为资源 – victor
  5. 访问php文件显示500错误,nginx 访问.php文件正常,访问.html文件500错误
  6. python3 image_python3 ImageTk 安装方法
  7. python将数据写入excel_【Python】将数据库中的数据查询出来自动写入excel文档
  8. ios13苹方字体ttf_字体 | iOS1013 SF Compact Rounded 英文 By alex
  9. 安装php7的mysql扩展,php7安装mysql扩展的方法是什么
  10. Java中String类 compareTo()方法比较字符串详解