毕包是一个比较抽象的开概念。对于我们这些新手来说,其中的一些特性是很难理解的。
在理解它之前,我们应先弄清楚什么是作用域链。作用域链可理解为:在函数定义时创建的的一个索引,用来寻找函数中变量的值。它的规则:函数自身本地变量放在最前面,父级函数变量放在其次,祖父~~~~。当需要查找某个变量时,js解释器就现在自身函数里面查找,如果没查到,就在去父级函数里面查找,父级没有的话就去更外一层的函数查找,如果到最后都没有查找的就返回undefined;
其次,我们还需要了解js的内存回收机制。一般情况下,函数开始执行的时候,会给其中的变量留一个空间用于保存它们,以备后面语句用。当函数结束的时候,变量就无用了,这个空间就回收了。当函数再次启动的时候就会重复刚刚的步骤。但是当这个函数中有另外一个内部函数时,那么这个函数若需要父级函数里面的变量的时候,就读取不到所需变量的值。所以在这个时候,js解释器就会形成一个“包包”将这个函数及父级函数里面的变量打包起来。不会被回收。此时的”包包“既是毕包。当内部函数被删除或者指针不在时,毕包也就被被销毁了。
作用域链:
function boke(){
var x=1;
testtwo = function(){
alert(x);
}
testtwo();
}boke();//此时变量在父级函数里面 得到1.
function boke(){
var x=1;
testtwo = function(){
var x=2;
alert(x);
}
testtwo();
}boke();//此时已在本函数里找到变量 就到此为止了。且得到2;
var x=1;
function boke(){
testtwo = function(){
alert(x);
}
testtwo();
}boke();//此时本函数,父级函数都没有就一直往上找。得到1;
function boke(){
testtwo = function(){
alert(x);
}
testtwo();
}boke();//此时本函数,父级函数都没有就一直往上找。返回undefined;
毕包:
function exercise(){
var z = 1;
addinfo = function(){z*=2;}
function exerciseone(){ alert(z+1); }
return exerciseone;
}
var closure = exercise();
addinfo();
closure();//得到3
此时exercise函数里面就有内部函数exerciseone,所以此时js解释器就会生成一个毕包,将exercise中的变量及函数保存在毕包中。所以:
function exercise(){
var z = 1;
addinfo = function(){z*=2;}
function exerciseone(){ alert(z+1); }
return exerciseone;
}
var closure = exercise();
addinfo();
addinfo();
closure();//得到5.
当内部函数被删除或者指针不在了,毕包也及相应的被销毁了。
function exercise(){
var z = 1;
addinfo = function(){z*=2;}
function exerciseone(){ alert(z+1); }
return exerciseone;
}
var closure = exercise();
closure();得到2;
综上所述,毕包有两个优点:①读取函数内部变量;②让函数内部变量的值一直保存(内存中)。