既然说闭包的化,我们就先来说说函数。慢慢的进入进入正题
(1)函数申明
f1(); function f1(){ alert("1") }//结果 1
(2)函数定义
f1();
var f1=function(){
alert(''1")
}// 直接报错了
其实原因是这样的函数申明:会在代码执行之前提前加载到作用域中这样在执行发f1()的时候就可以找到了。但是函数的定义是:先在内存里卖弄创建了一块区域,之后通过一个f1() 指针指向这块区域,开始的时候这块区域是没有名字的.
函数的作用域链
var number="a"; var showNumber=function(){ alert(this.number); } function changeNumber(){ var anothernumber="b"; function savenumber(){ var tempnumber=anothernumber; anothernumber=number; number=tempnumber } savenumber(); } changeNumber(); showNumber() //结果是“b”
其实我的理解就是,在进行js 函数调用的时候,会为每一个函数自动的添加一个scope属性通过这个属性来指向一块内存,然后这个内存就会包含这个这个函数的上下文相关的变量,如果这个函数里面又包含了一个新的函数,那么又会自动的分配一块内存,当然这个函数又会自动的继承了他的上级所执行的变量(这个继承可能说的不太对感觉是这个意思?)
函数作用域链:示意图
其实可以这么理解哈。我们在带调用changnumber()的时候首先changenumber()这个函数的作用域链包括自己的(anothernumber 这个变量,然后就是savenumber()。最后就是上文的作用域,也就是number()和shownumber()这个全局的。这个时候savenumber 也会被执行那么他就会去继承他的上一级的作用域,和上上级的作用域,)那么这个时候savenumer去改变number 的值,这个时候number 的值就是b,最后当我们调用shownumber()的时候自然出现的值就是结果“b”了。
我看一个例子看看闭包产生的原因:
function compareObjectFunction(prop){ //匿名函数 return function(obj1>obj2{ if(obj1[prop]>obj2[prop]) return 1; else if(obj1[prop<obj2[prop]]) return -1; else return 0; }) } var o1={name:"Leon",age:23}; var o2={name:"Ade",age:28}; /* 在中这个时候变量并没有被释放,于是这个时候作用域就变大了 */ var compare=compareObjectFunction("age"); var rel=compare(o1,o2); alert(rel1)
我们看看他的作用域链
于是我们来解释一下到底是如何实现的。首先我们执行compareobjectfunction()的时候会产什么如下的作用域链Global和compareobject()这个。当compareobjecfunction执行完过后我们就会释放相应的作用域但是这个时候com这个匿名函数指向了相同的作用域,Global和compareobject()这个时候并不会发生释放这个作用域的动作,于是compar、这个就获取到相应的参数了。于是乎作用域就发生了扩大。这个就是闭包产生的原理。其实我的理解就是里面的函数调用了外部函数的变量(或者说扩大了函数的访问变量的范围)
下面我们再来看一个例子:
function fn1(){ var fns=new Array(); for(var i=0;i<10;i++){ fns[i]=function(){ return 1; } } return fns; } var fs=fn1(); for(var i=0;i<fs.length;i++) { alert(fs[i]()) }
注释:参考孔浩