js闭包

一、在说闭包之前,首先需要了解两个东西

执行上下文(EC):简单来说,抽象点可以看做一个对象{}的格式(调试里的scope作用域);里面存储着函数里面定义的所有变量。
     js中只有函数可以创建上下文(执行环境)。

垃圾回收机制(GC):js具有垃圾回收机制;就是说执行环境会负责管理代码执行过程中使用的内存。原理就是找出不再使用的变量,然后释放其占用的内存。垃圾回收器会按照固定时间间隔周期性的执行这一操作。或者内存占用过大的时候,去遍历所有的变量;如果没有其他变量引用它,就释放内存。

js垃圾回收机制主要有两种策略:1、标记清除;2、引用计数

标记清除:就是当变量进入环境的时候,就把其标记为’进入环境’,永远不会清除,只有当变量离开环境时,才会把其内存释放。

引用计数:就是跟踪每个值引用的次数,当声明一个变量并赋值一个引用类型赋值引用次数加1;如果同一个值又被赋值给另一个变量,该值引用次数再加1;相反如果包含这个值的引用比变量又取得另外的值,则该值引用次数减1。当引用次数为0。说明无法引用该值了;就可以释放内存了。

js最常用的是标记清除的策略;最不常用的是引用计数,因为引用 计数在Netscape Navigator 3.0最早使用时,出现了一个严重的问题;循环引用。循环引用指:对象A包含一个指向对象B的指针;而对象B也包含一个指向对象A的引用。此时它们的引用次数都是2;所有不会释放内存。


下面看看一个例子:
<script>
    /**
     * a、b为参数变量
     * p、q为var定义的
     * m:为函数声明
     *
     * 这些变量都会变量上浮。
     * 除了函数声明,其他类型变量只是定义上浮了而已;所以函数声明在声明的前面,就可以调用;
     * 而其他类型变量在声明的前面不可以调用,会出现undefined
     *
     * @param a
     * @param b
     */
    function fn(a,b){
        m();
        console.log(q);

        var p=1;
        var = function () {
            console.log('q')
        };

        function m(){
            var 1;
            function y(){
                console.log('y')
            }
            console.log("m");
        }
        m();
    }
    fn();
</script>

二、闭包

函数创建上下文的时候会调用堆栈,栈的特点是:先进后出;每创建一个上下文就会往栈压入一个上下文;函数执行完就会弹出此上下文。

闭包比较特殊;虽然也已经弹出了栈;但是它还被其它的引用着;所以垃圾回收集没有对它进行回收,还存在着。由此就形成了闭包。

自由变量:函数里面引用外面定义的变量,叫自由变量。

闭包的表层理解:当一个函数执行时,返回一个函数,这个函数还可以引用这个执行函数内部的变量。这种情形叫闭包。

闭包的深层理解:当函数执行完时,它的上下文(EC)被弹出了堆栈,但是它还有被别的变量引用着,所以垃圾回收集(GC)没有对它进行回收,还存在着。由此就形成了闭包。

例子:
function fn(a,b){
    var m1;
    var = function(){
        console.log('n');
    };

    var = function(){
        console.log(m);
        n();
    };

    return p;
}

var ret fn();
ret();










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值