闭包

来源:互联网 发布:html数据库添加div 编辑:程序博客网 时间:2024/05/29 17:53
刚开始接触闭包时,被闭包搞得头晕目眩,就知道闭包是函数里面嵌套函数,看了视频查阅了书籍之后明白了闭包的原理及作用。

理解闭包首先要先理解执行环境和作用域链。执行环境定义了变量或函数有权访问的其他数据,决定了它们的行为。每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,而函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。作用域链由一个全局对象组成,。在不包含嵌套函数的函数体内,作用域链上有两个对象,第一个是定义函数参数和局部变量的对象。第二个是全局对象。在一个嵌套的函数体内,作用域链上至少有三个对象。当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来储存它的局部变量,并将这个对象添加至保存的那个作用域链上,同时创建一个新的更长的表示函数调用的作用域的“链”。函数对象可以通过作用域链关联起来,函数体内部变量都可以保存在函数作用域内,这种特性成为“闭包”。

理解闭包首先要了解嵌套函数的词法作用域规则。看一下这段代码
var scope = "global scope";
function checkscope() {

var scope = "local scope";
function f(){return scope;}
return f();

}
checkscope(); //"local scope"


我们对代码做一点改动,将函数内的一对圆括号移动到了checkscope()之后。代码如下

var scope = "global scope";
function checkscope() {

var scope = "local scope";
function f(){return scope;}
return f;

}
checkscope()(); //"local scope"

我们可以看到两者执行的结果是一样的,js函数执行用到了作用域链,这个作用域链是函数 定义的时候创建的。嵌套函数f()定义在这个作用域链里,其中变量scope是局部变量,不管在何时何地执行函数f(),这种绑定在执行f()时依然有效。

闭包的实现,我们将作用域链描述为一个对象列表,每次调用js函数的时候,都会为之创建一个新的对象用来保存局部变量,把这个对象添加至作用域链中。当函数返回的时候,就从作用域链中将这个绑定变量的对象删除。如果不存在嵌套函数,也没有其他引用指向这个绑定的对象。它就会被当做垃圾回收掉。如果定义了 嵌套的函数,每个嵌套的函数都各自对应一个作用域链,并且这个作用域链指向一个变量绑定函数,但如果这些嵌套的函数在外部函数中保存了下来,那么也会和所指向的变量绑定对象一样当做垃圾回收,但如果这个函数定义了嵌套函数,并将它 作为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套函数。它就不会被当做垃圾回收,并且它所指向的变量 绑定对象也不会被当做 垃圾回收。


原创粉丝点击