JavaScript作用域、作用域链、以及闭包

534 阅读3分钟

作用域:

作用域是可访问变量的集合。

  • 在 JavaScript 中, 对象和函数同样也是变量。
  • 在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。
  • JavaScript 函数作用域: 作用域在函数内修改。

作用域分类:

  • 全局作用域 和局部作用域

局部作用域:

  • 变量在函数内声明,只能在函数内部访问,即局部变量
  • 函数参数也是局部变量
  • 因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。

全局作用域:

  • 变量在函数外定义,即为全局变量
  • 全局变量有 全局作用域: 网页中所有脚本和函数均可使用。

作用域链

概念:当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值。但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链

function foo() {
    let a = 1;
    function bar() {
        let a = 2;
        function baz() {
            let a = 3;
            console.log(a);  //3 
        }
        baz();
    }
    bar();
}
foo();

作用域如图

 let a = 1;
        function foo() {          foo的作用域
            let a = 2;
            function baz() {       baz的作用域  
                console.log(a);
            }
            bar(baz);                   
        }                                       
        function bar(fn) {         bar的作用域
            let a = 3;
            fn();
            console.log(fn); // baz
        }
        foo();

什么是闭包?

  • 闭包是有权访问另一个函数作用域中的变量的函数,实质上是将函数内部与外部连接起来的桥梁。---js高级教程

为什么会有闭包?

  • 之所以出现闭包是因为JS的垃圾回收机制,JS 本身为了避免解释器过量消耗内存,造成系统崩溃, 自带有一套垃圾回收机制,垃圾回收机制能够检测到一个对象是不是无用的。检测到之后,就会把它占用的内存释放掉。但是实际工作中,我们也会需要一些变量不那么及时的被清理,所以就出现了闭包,用来达成这个效果。

闭包的特点

1、函数套函数;

2、内部函数有权访问外部函数的变量;

3、参数和变量不会被垃圾回收机制收回。

 function F1(){
            let a = 100; 
            return function f2(){  // 闭包的特点:1. 函数套函数
                console.log(a)  // 2. 内部函数可以引用外部变量
            }
        }
        let f1 = F1();
        let a = 200 ;  // 重新定义变量来看看调用时走哪个
        f1();  // 100  函数调用时的变量是创建时候的变量而不是调用时的变量

如何清除闭包

  • 我感觉闭包只要闭包里面的变量不被引用就不会造成影响 但实际上不是这样的 下面的正解
  • 闭包的含义是函数在调用时能够访问函数在定义时可以访问的作用域,例如在定义函数a的时候,a能够访问变量b。每一个函数都有自己对应的闭包,当函数没有被垃圾回收机制回收时函数对应的闭包也会常驻内存。如果需要清除闭包就要回收不需要的函数,根据JavaScript回收机制,当一个内存空间没有变量指向的时候就会被回收。那么闭包清除的方式就是将不需要的函数名赋值为null。