闭包

  • 闭包是函数和声明该函数的词法环境的组合。 ----MDN
  • 闭包就是指有权访问另一个函数作用域中的变量的函数。 ----红宝书

    闭包的特性

    1. 函数嵌套函数
    2. 内部函数可以访问外部作用域(或外部函数)的变量和参数
    3. 参数和变量不会被回收机制回收,一直存在于内存中,除非手动清除

    为什么要用闭包

    1. 希望变量长期存在内存中
    2. 避免全局变量污染

    闭包举例及应用

    function outer() {
        var a = 1;
        return function() {
            return a; // 内部函数访问外部作用域的变量a
        }
    }
    var b = outer(); // 这一句执行完,变量a并没有被回收,因为要内部函数还需要引用
    console.log(b()); // 1 执行内部函数,引用外部变量a
    

    闭包的缺陷

    **闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露**
    *如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。*
    

作用域

  • 作用域是一个变量和函数的作用范围,JS中函数内声明的所有变量在函数体内始终是可见的,在ES6前有全局作用域和局部作用域,但是没有块级作用域(catch只在其内部生效),局部变量的优先级高于全局变量。

作用域链

Javascript中有一个执行上下文(execution context)的概念,它定义了变量或函数有权访问的其它数据,决定了他们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中

  • 当访问一个变量时,解释器会首先在当前作用域查找标示符,如果没有找到,就去父作用域找,直到找到该变量的标示符或者不在父作用域中,这就是作用域链。

作用域链和原型继承查找时的区别:如果去查找一个普通对象的属性,但是在当前对象和其原型中都找不到时,会返回undefined;但查找的属性在作用域链中不存在的话就会抛出ReferenceError。

作用域链的顶端是全局对象,在全局环境中定义的变量就会绑定到全局对象中。

闭包的作用域链包含着它自己的作用域,以及包含它的函数的作用域和全局作用域。