闭包:当内部函数被保存到外部时,会生成闭包。闭包的原理其实是内部函数或里面变量,被外部或者其他变量所引用,那么这个函数的当前作用域就无法被释放。闭包会导致原有作用域链不释放,造成内存泄漏。
function test(){
var arr=[];
for(var i=0;i<10;i++){
arr[i]=function(){
document.write(i+" ");//赋值语句,函数引用的时候不会管后面函数体的内容,只有函数执行的时候才会读i的值
}
}
return arr;
}
var myArr=test();
for(var j=0;j<10;j++){
myArr[j]();//函数执行,10个都公用一个执行期上下文
}
解决方式
function test(){
var arr=[];
for(var i=0;i<10;i++){
(function(j){
arr[j]=function(){
document.write(j+" ");
}
}(i));
}
return arr;
}
var myArr=test();
for(var j=0;j<10;j++){
myArr[j]();//每执行一次循环都会产生一个新的立即执行函数,都会有自己的AO
}
闭包的作用
- 实现公有变量:例如函数加速器
function add(){
var num=0;
function a(){
console.log(++num);
}
return a;
}
var myAdd=add();
myAdd();
myAdd();
- 可以做缓存(存储结构):例如eater
function test(){
var food='apple';
var obj={
eatFood:function(){
if(food!=""){
console.log("I am eating "+food);
food="";
}else{
console.log("nothing is here!");
}
},
pushFood:function(myfood){
food=myfood;
}
}
return obj;
}
var person=test();
person.eatFood();
person.pushFood("banana");
person.eatFood();
- 可以实现封装,属性私有化:例如Person()
function Person(name,wife){
var prepareWife="xiaozhang";
this.name=name;
this.wife=wife;
this.divorce=function (){
this.wife=prepareWife;
}
this.changePrepareWife=function(target){
prepareWife=target;
}
this.ayPrepareWife=function(){
console.log(prepareWife);
}
}
var person=new Person('du','xiaohong');
//在这个里面我们用person.prepareWife是找不到的,实行了一个属性的私有化,只能通过里面的方法来查看,里面的函数是可以看到这个属性的。并且可以使用。
- 模块化开发,防止污染全局变量
var init1=(function(){
var name=123;
function callName(){
console.log(name);
}
return function(){
callName();
}
}());
//互不影响
var init2=(function(){
var name=45;
function callName(){
console.log(name);
}
return function(){
callName();
}
}());