【JavaScript】【作用域】作用域和作用域链

129 阅读3分钟

一、作用域

1.1 概念

什么是作用域:作用域变量和其他运行时代码中的某些特定部分中变量、函数和对象的可访问性。决定了代码区块中变量和其他资源的可见性。

1.2 作用域种类

  • 全局作用域:在代码中任何位置都能访问到的对象拥有全局作用域。
    • 作用范围是全局
    • 所有未定义直接复制的变量自动生命为拥有全局作用域
    • 所有window队形的属性拥有全局作用域
  • 函数作用域:生命在函数内部的变量,和全局作用域相反。
    • 作用范围是这个函数内部
    • 局部作用域一般只在固定的代码片段内可访问到
  • 块级作用域:块语句({}中间的语句),如if和switch条件语句,for和while循环语句,不同于函数,它们不会创建一个新的作用域;
    • ES6之后出现的
    • 作用范围是这个块语句内部
    • 新增命令let和const声明,所声明变量在指定块的作用域外无法被访问

1.3 作用域作用

  • 作用域最为重要的一点是安全。变量只能在特定的区域才能被访问,外部环境不能访问内部环境的任何变量和函数,即只可以向上搜素,不可以向下搜素。有了作用域我们就可以避免在程序其他位置意外对某个变量做出修改导致程序发生事故。
  • 作用域能够减轻命名的压力。我们可以在不同的作用域内定义相同的变量名,并且这些变量名不会产生冲突。

二、作用域链

2.1 自由变量

  • 自由变量:当前作用域中没有定义的变量
  • 自由变量取值方式:要到创建这个函数的那个作用域中取值

2.2 作用域链(scope chain)

  • 什么是作用域链(scope chain):多个作用域对象连续引用形成的链式结构。

    • 使用方面解释:当在JavaScript中使用一个变量的时候,首先JavaScript引擎会尝试在当前作用域下去寻找该变量,如果没找到,再到他的上层作用域寻找,以此类推直到找到该变量或是已经到了全局作用域,如果在全局作用域里仍未找到该变量,他就会直接报错。
    • 存储方面解释:作用域链在JS内部中是以数组的形式存储的,数组的第一个索引对应的是函数本身的执行期上下文,也就是当前执行的代码所在环境的变量对象,下一个索引对应的空间存储的是该对象的外部执行环境,以此类推,一直到全局执行环境
    var a = 100, d = 500;
    function func() {
        var b = 200, d = 600;
        console.log(a) // 100,在当前作用域未找到,就到上层作用域找,并找到了
        console.log(b) // 200,在当前作用域找到了
        console.log(d) // 600,在当前作用域找到了
        console.log(C) // undefined,在当前、上层、全局作用域都为找到
    }
    func();
    
  • 作用域链的特点

    由于变量的查找是沿着作用域链来实现的,所以也称作用域链为变量查找的机制

  • 作用域链的作用

    是保证对执行环节有权访问的变量和函数的有序访问,通过作用域链,可以访问到外层环境的变量和函数。

  • 作用域链的本质

    是一个指向变量对象的指针列表。变量对象是一个包含了执行环境中的所有变量和函数的对象。变量对象是一个包含了执行环境中所有变量和函数的对象。作用域链的前端始终都是当前执行上下文的变量对象。全局执行上下文(全局对象)的变量对象始终是作用域链的最后一个对象。

资料来源