Mr.J--JS学习(闭包及IIFE)

版权声明:转载请标明出处 https://blog.csdn.net/Ms_yjk/article/details/86582363

     首先,一个小小的题目:将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]();		
			}

运行结果:

以上若有不足之处,还请指出。

猜你喜欢

转载自blog.csdn.net/Ms_yjk/article/details/86582363
今日推荐