JavaScript学习之闭包

2021-06-14  本文已影响0人  愤怒的小猪

闭包的概念

    函数对象可以通过作用域i链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为"闭包"。

    我的理解是,只要是内部的函数被保存到了外部,就一定会生成闭包。或者说只要是能访问其他函数内部的变量的函数就是闭包。

举个例子:

function a(){
    function b(){
        console.log(aaa)
    }
    var aa = 123;
    return b;
}
var demo = a();
demo();

闭包的好处

  1. 可以读取函数内部的变量

  2. 可以让变量是始终保存在内存中,比如:单例

     var Singleton = function(name) {
            this.name = name;
        };
    
        Singleton.prototype.getName = function() {
            alert(this.name);
        };
    
        Singleton.getInstance = (function() {
            var instance = null;
    
            return function(name) {
                if (!instance) {
                    instance = new Singleton(name);
                }
                return instance;
            }
        }());
    
        Singleton.getInstance("12312").getName()
    

闭包的危害

  1. 使用不当则会产生内存泄漏

理解

我们知道为什么了闭包的好处与危害,那么为什么闭包可以让变量始终保存在内存中,为什么会产生内存泄漏呢?

1. 为什么闭包可以让变量始终保存在内存?
function a(){
    function b(){
        var c = 0
        console.log(aaa)
    }
    var aa = 123;
    return b;
}
var demo = a();
demo();
a函数被执行时会产生自己AO,当b函数被执行时也会产生自己的AO同时拥有a函数的AO。正常情况下a函数执行完以后,会释放自己的AO,b函数执行完以后也会释放自己的AO。但是现在b函数被a函数返回出来了,同时赋值给了demo,那么现在在demo就拥有了b的AO,如果demo一直不被销毁,那么b的作用域链就会一直存在内存中。
a.[[scope]] = [
    // AO
    {
        this:window,
        aa:123,
        b:(function)
    },
    // GO
    {
        this:window
        window:(Object),
        document:(Object)
        a:(function),
        demo: (function),
    }
]

b.[[scope]] = [
    // AO
    {
        this:window,
        c:0
    },
    // AO
    {
        this:window,
        aa:123,
        b:(function)
    },
    // GO
    {
        this:window
        window:(Object),
        document:(Object)
        a:(function),
        demo: (function),
    }
]
  1. 为什么会产生内存泄漏?

    如果闭包一直占用内存不被释放,会导致系统占用的内存越多,可以使用的内存越少,这也是一种内存泄漏。

上一篇 下一篇

猜你喜欢

热点阅读