19.js中闭包

js中闭包
    var name = "Microsoft";
    function funcA(){
        var name = "Google";
        alert(name);
        return function(){
        name = "Facebook";
        alert(name);
        };
    }
    var o = funcA(); //Google
    alert(name); //Microsoft
    o(); //Facebook
    ******************
        执行完后,执行流就会离开funcA, 那么funcA的变量对象就应该被销毁了。
        作用域链的创建规则是复制上一层环境的作用域链,并将指向本环境变量对象的指针放到链首;
    ******************
    匿名函数的作用域链应该有三个元素,第一个是匿名函数的变量对象指针,第二个是funcA的变量对象指针,第三个是全局变量对象指针。根据搜索算法,首先搜索匿名函数的变量对象,显然这个对象中不存在name,然后搜索funcA的变量对象,这里面有个“name”,因此将其作为name变量返回,搜索终止,所以,匿名函数引用的是funcA内定义的“name”变量而非全局变量。
    var o = funcA();
    执行完后,执行流就会离开funcA, 那么funcA的变量对象就应该被销毁了,funcA内定义的变量name就应该不存在了,为什么在后面还可以访问到呢?要解释这个问题,请回想上文一句话:作用域链的创建规则是复制上一层环境的作用域链,并将指向本环境变量对象的指针放到链首;根据这句话我们知道匿名函数的作用域链有三个元素,引用了三个变量对象(上文有说),这里要注意,返回的匿名函数赋值给了变量o,而变量o是一个全局变量,在funcA执行完成后不会被销毁。当赋值的时候,匿名函数的作用域链已然建立,并且此作用域链引用了funcA的变量环境,因此,当funcA执行完毕后,其执行变量和作用域链确实被销毁了,但是其变量对象没有被销毁,因为匿名函数的作用域链对其有引用,其无法被垃圾回收机制销毁。当funcA执行完成后funcA的Scope chain早就销毁了,但是其变量对象(红色表示),因为被匿名函数的Scope chain引用了,所以没有销毁。因此,匿名函数可以访问其成员,当匿名函数执行完成后,它会连同匿名函数的Scope chain一起被销毁。
    闭包就是能访问另一个函数作用域中变量的函数。
    因为闭包通常通过匿名函数实现,所以经常有人将闭包和匿名函数两个名词混用。闭包的优点很明显,就是可以访问另一个函数域中的变量,缺点也明显,比较耗内存(因为同时保持了N个变量对象)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章