当一个内部函数被调用,就会形成闭包,闭包就是能够读取其他函数内部变量的函数。阅读下面函数思考
function a(){
function b(){
var bb = 234;
console.log(aa);
}
var aa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();
当a函数被定义时,预编译产生全局变量GO:
当a函数要执行时,执行前一刻(预编译产生局部变量AO):
a函数执行后销毁自己的AO,回到被定义的状态
之后b函数被定义在a函数的环境内,预编译产生全局变量GO(可以这样理解,相对于b来说,此时它的GO是a执行时的AO):
然后b被保存到了外部,但身上保存了a的劳动成果
例:
function a(){ //a defined a.[[scope]]- 0:GO
function b(){ //a doing a.[[scope]]- 0:AO; 1:GO
function c(){//b defined b.[[scope]]- 0:aAO; 1:GO
};
c(); //b doing b.[[scope]]- 0:bAO; 1:aAO; 2:GO
};
b(); //c defined c.[[scope]]- ......
};
a(); //c doing c.[[scope]]- 0:cAO; 1:bAO; 2:aAO; 3:GO
所以内部被保存到了外部,必定生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏(被占用)
1.累加器的应用
function add(){
var count = 0;
function demo(){
count ++;
console.log(count);
}
return demo;
};
var counter = add();
counter();
counter();
函数每被调用一次。实现一次累加。
2.缓存应用
obj保存着两个函数被return返回到了外部。
function eat(){
var food = "";
obj = {
eater : function (){
console.log("I'm eat "+food);
food = "";
},
push: function (myfood){
food = myfood;
}
}
return obj;
}
var eater1 = eat();
eater1.push("饭");
eater1.eater();
function a(){
function b(){
}
return b;//利用return将b函数返回
};
var demo = a();
var demo;
function a(){
function b(){
}
demo = b;
}
a();
demo();
只要将内部函数被保存到外部就可以形成闭包,形式多样
1.立即执行函数的两种常见形式
1.(function(){ }())
w3c显示这种好
2.(function(){ })()
例:
var num = function (a,b,c){
var d = a+ b + c;
return d;
}(1,2,3));//初始化后抛回
只有表达式才能被执行符号执行
var test = function(){
console.log("a");
}();//函数体后面要有小括号(),函数体必须是函数表达式而不能是函数声明
!function test(){
console.log('a');
}();//(),!,+,-,=等运算符都能起到立即执行的作用,这些运算符的作用就是将匿名函数或函数声明转换为函数表达式
立即执行函数执行后放弃函数名字(即失去索引,成为一次性的),再输出test为undefined
2.特殊情况
function test(a,b,c){
console.log(a+b+c);
}
(1,2,3);//该形式会被读成下面写法
function test(a,b,c){
console.log(a+b+c);
}(1,2,3);//改写法既不报错,也不执行
1.例
function test(){
var arr = [];
for(var i = 0;i < 10;i ++){
arr[i] = function (){
console.log(i);
}
}
return arr;
}
我们原意是写一个数组能够输出它自己的索引,但实际情况是:
因为js在进行预编译时,只是arr[i]=函数(被没有访问内部),然后i++到10时退出循环,导致真正执行时i=10。
解决方法
利用立即执行函数
function test(){
var arr = [];
for(var i = 0;i < 10;i ++){
(function (j){
arr[j] = function (){
console.log(i);
}
}(i));
}
return arr;
}
注:闭包和立即执行函数,不会互相污染变量。
var x = 1;
if(function f(){}){
x += typeof f;
console.log(x);
}
答案和解析下一期揭晓!