JS立即执行函数

JS立即执行函数形式与具体应用

首先分清函数声明和函数表达式

//函数声明:
function a() {
	//.....
}
//函数表达式:
var b = function(){
	//.....
}

注意:函数声明在预编译时,会被提升到最顶部
函数表达式不会被提升

立即执行函数的写法

当一对圆括号跟在函数表达式之后,该函数将成为立即执行函数
立即执行函数的两种常用写法:

(function (){
	//执行代码
}());
	
(function (){
	//执行代码
})();

//基本原理可以理解为:
var abc=function(){
	console.log(123);
}
abc();

立即函数的实参与形参位置

(function ( a, b, c){
	console.log(a + b + c);
})( 1, 2, 3);

//可以理解为:
var abc=function( a, b, c){
	console.log(123);
}
abc( 1, 2, 3);

! + - = ()等运算符都能将函数声明匿名函数转换为函数表达式
例如立即执行函数的其他写法:

+ function a(b){
	nsole.log(b);
}(123)  //打印出123

- function a(b){
	console.log(b);
}(123)  //打印出123

! function a(b){
	console.log(b);
}(123)  //打印出123

但是当立即执行函数有返回值时,! + -这些符号也会和返回值进行运算,从而出现不必要的麻烦,例如:

var a=!function(){
	return 123;
}()
console.log(a);  //打印出false,因为a接受的为!123运算后的值

所以推荐使用以上两种用()包裹的方法

立即执行函数的应用

  1. 页面的初始化工作(执行完成后销毁,不会占用空间)
  2. 避免污染全局变量
  3. 只执行一次的代码需要变量,将这些临时变量定义成全局变量会非常不好,这时可以将这些变量包裹在立即执行函数中
  4. 立即执行函数会形成一个单独的作用域

一个典型的例子:

function demo(){
	var arr=[];
	for(var i = 0; i < 10; i++){
		arr[i]=function(){
			document.write(i+" ");
		}
	}
	return arr;
}
//循环执行函数,并打印值
var myarr = demo();
for(var k = 0; k < 10; k++){
	myarr[k]();
}

最后输出十个10,并不是0到9
因为在该段代码中,生成了十对一的闭包,在匿名函数中的 i 并不会在赋值过程中变现(替换为数字)
arr数组的所有函数拿到的均为demo产生的执行期上下文对象(AO),所以他们共用一个 i
当循环触发时,在向demo中的AO寻找 i 时,i 已经变为10,所以全部打印10

function demo(){
	var arr=[];
	for(var i = 0; i < 10; i++){
		//通过立即执行函数,生成十对十的闭包
		//每个函数拿到的都是立即执行函数的执行期上下文(AO),所j不同
		(function(j){
			arr[j]=function(){
				document.write(j + " ");
			}
		}(i));
	}
	return arr;
}
var myarr = demo();
for(var k = 0; k < 10; k++){
	myarr[k]();
}

通过立即执行函数解决了这一问题,每个匿名函数都在立即执行函数中,即每个函数都有各自的立即执行函数的AO对象
所以每个函数所打印的 j 即为各自AO对象中的 j(因为立即执行函数运行后会被销毁,所以每次循环都会创建新的AO对象,各自 j 的值不会互相影响)