Mr.J--JS学习(闭包及IIFE)
首先,一个小小的题目:将10以内的数字进行输出。相信大家看到这个题目一定会感到非常熟悉,这不就是一层简单的for循环吗? 不就是这样一段demo:
function test1(){var count = 0;for(var i =0; i < 10;i++){document.write(i+" ");}}test1();
运行结果就是:0 1 2 3 4 5 6 7 8 9
相信上面的题目只要学过编程的人都会轻松的写出来。那么题目要求改变一下:要求输出一个数组内的10个函数的索引值。函数索引值?直接把数组角标输出不就行了,比上面多两行代码而已,代码如下:
function test(){var arr = [];for(var i = 0;i < 10;i ++){arr[i] = function(){document.write(i + " ");}}return arr;}var myArr = test();for(var j = 0;j < 10;j++){myArr[j](); }
从上面的代码可以看见:使用for循环给数组内储存十个函数,并调用函数再次使用for循环输出。看起来简直天衣无缝。但是....运行结果却是这样的:
当我看到这个运行结果我也很纳闷。首先,输出10个数。这是毋庸置疑的。但是10个数一样就很怪异了,更让人费解的是为什么输出了10,输出10个9我能理解(第一段demo输出0-9)。
闭包
闭包包含自由(未绑定到特定对象)变量,这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。
function a(){function b(){ //内部函数var bbb = 234;console.log(aaa); }var aaa = 123;}var glob = 100;var demo = a();demo();
从上面的demo可以看到,先进行定义a函数,a函数内部有一b函数,b函数用控制台进行aaa的输出。最后用demo将a进行调用,程序结束。 相信有一半的人会认为是这样,运行结果是:
不但没有结果,还出现了报错。请再把闭包的概念看一遍:变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。作用域不同,其实就是局部变量不能在全局使用。只需一行即可完成demo。
function a(){function b(){ //内部函数var bbb = 234;console.log(aaa); }var aaa = 123;return b; //return 返回外部(保存在外部) 闭包}var glob = 100;var demo = a();demo();
运行结果:
现在我们返回第二个题目,输出函数索引。可能有人会想直接加一个return arr,把数组返回到外部就OK了,但是仔细看demo,已经存在返回的数组arr。
为什么会是10?
当i加到9的时候,9<10,再进行i++;
为什么会有10个10?
函数在外部for循环进行调用,那么已经在函数内部进行了预编译,此时的i值已经全部变成了10,外部再一个一个的进行调用,所以输出了10个10。
如何改正demo使其正确?
引入概念:立即执行函数(IIFE)。
Javascript和其他编程语言相比比较随意,所以Javascript代码中充满各种奇葩的写法,有时雾里看花,当然,能理解各型各色的写法也是对javascript语言特性更进一步的深入理解。其中( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法。
首先得知道这三个名词:函数声明,函数表达式,匿名函数。
函数声明: function fnName() {...} ;
使用 function 关键字声明一个函数,再执行一个函数名,叫函数声明。
函数表达式: var fnName = function() { ... } ;
使用 function 关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。
匿名函数: function() { ... } ;
使用 function 关键字声明一个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。
以下是我今天听课所学习到的关于立即执行函数的知识:
//立即执行函数//针对初始化功能的函数 执行完就被释放(function (){var a = 123;var b = 234;console.log(a+b);}())var num = (function(a,b){var c = a+b*4;return c;}(234,564));console.log(num);//(function(){}()); //建议第一种//(function(){})();//只有表达式才能被执行符号执行function test(){var a = 213;}test();var test = function(){console.log('a');}//能被执行符号执行的表达式变成立即执行函数var test = function(){console.log('a');}();+ function test(){ //+ - ! (*和/不行 + - 是正负不是加减)console.log('a');}();var num = function test(a , b , c , d){console.log(a+b+c+d);}(1 , 2 , 3 , 4);
通过闭包和立即执行函数,这是我们就可以改正我们之前的demo了。
function test(){var arr = [];for(var i = 0;i < 10;i ++){(function (j){arr[j] = function(){console.log(j + " ");}}(i));}return arr;} var myArr = test();for(var j = 0;j < 10;j++){myArr[j](); }
运行结果:
以上若有不足之处,还请指出。
Mr.J--JS学习(闭包及IIFE)相关推荐
- 你不懂的JS学习笔记(作用域和闭包)
You don't KnowJS 引语:你不懂的JS这本书github上已经有了7w的star最近也是张野大大给我推荐了一波,阅读过之后感觉对js的基础又有了更好的理解.本来我是从来不这种读书笔记的, ...
- js学习笔记(执行上下文、闭包、this部分)
1.函数的准备工作 函数在执行会进行一些准备工作,如创建一个"执行上下文"环境:执行上下文可以理解为当前代码的执行环境,它会形成一个作用域: 每个碰到可执行代码的时候都会进行这些& ...
- sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map)
sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map) 这几天学习和查看了jQuery和Property这两个很流行的前端库的御用选择器组件Sizzle.js的源代码,收获还是相对多的!之 ...
- 用闭包实现重载的过程学习闭包
用闭包实现重载的过程学习闭包 let global = {overLoad:function(){} }; function Refactoring(func) {let oldFunc = glob ...
- 利用js的闭包原理做对象封装及调用方法
创建一个js文件,名为testClosure.js: ? 1 2 3 4 5 6 7 8 9 (function () { function a() { alert('i am a') ...
- javascript从入门到跑路-----小文的js学习笔记目录
** javascript从入门到跑路-----小文的js学习笔记(1)---------script.alert.document.write() 和 console.log 标签 javascri ...
- JS学习笔记(九)深拷贝浅拷贝【Array、Object为例】
JS学习笔记(九) 本系列更多文章,可以查看专栏 JS学习笔记 文章目录 JS学习笔记(九) 一.赋值&复制 二.浅拷贝(shallow copy) 1. 什么是浅拷贝 2. 数组的浅拷贝 ( ...
- Jquery真的不难~第八回 JS的闭包问题
百度百科中对闭包的定义: 闭包是可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义."闭包" 一词来源 ...
- ArcGIS JS 学习笔记4 实现地图联动
原文:ArcGIS JS 学习笔记4 实现地图联动 1.开篇 守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数.这次我的模仿目标是天地图的地图联动. 天地的地图联动不仅地图有联动,而 ...
- backbone.js学习笔记
backbone.js学习笔记 之前只接触过jQuery,看来Backbone是除了jQuery的第二大JS框架... backbone到底是个啥? 其实刚开始我也不知道=_=,我是这周二才听说居然还 ...
最新文章
- 后端如何发出请求_gRPC系列(三) 如何借助HTTP2实现传输
- 软件中常用的“发送邮件”、“打印文档”,其本质是“队列”!
- 极大似然估计的朴素理解
- 四十五、深入Java的网络编程(上篇)
- yum安装mysql和mysql源,配置mysql(亲测)
- 皇室战争:暗夜女巫重做,去掉亡语机制后,她凉的可能会更快
- STL源码剖析---deque
- 上交所行情文件导入数据库
- php根据浏览器调用支付_Android通过外部浏览器调用微信H5支付,Android+PHP详解
- php海外研发,国外主流PHP框架比较
- activeperl安装不成功_手把手教你:Windows系统上安装GPU深度学习环境
- 正则表达式 查找以某些字符开始 某些字符结束的匹配项 解决之道
- 【比赛】新冠肺炎疫情趋势预测大赛~推荐大家参加下
- 网页截图插件FireShot
- Mosquitto修改默认端口port
- JS网页特效实例:让网页前进和后退
- 计算机网络atm功能,现代计算机网络原理4ATM交换技术.ppt
- 定义一个方法,使用随机的字母+数字生成一个6位数的密码
- Jmeter实现多用户压测
- No mapping found for HTTP request with URI问题解决
热门文章
- CV Code | 本周计算机视觉新出开源代码汇总(含目标检测、深度估计、视频识别、网络加速算法等)...
- 超强!MDETR:基于Transformer的端到端目标检测神器!开源!
- 教程|YOLOX目标检测ncnn实现
- 经验 | 上交机械本硕转计算机视觉岗位面经
- 深度学习 | Why and How:神经网络中的权重初始化
- c语言判断回文字符串递归,用递归实现判断一个字符串是否为回文串
- 重复类发展手法_正确的护肤手法(动态演示),喜欢就拿去收藏吧!
- 计算机适配器有什么作用,例举适配器是什么
- java oop入门_java入门(十六) | OOP(三)之构造方法
- 32f4 usb 升级程序_不断中招的你还放心升级win10吗?wi10近期更新问题及解决办法...