JavaScript 中的作用域、作用域链以及延长作用域链?

399 阅读2分钟

1.作用域

作用域就是变量起作用的范围。在一定空间内,可以对数据进行读写操作,这个空间就是数据的作用域。

1.1全局作用域(全局变量)

在函数外部声明,页面任何地方都可以使用

1.2局部作用(局部变量)

在函数内部声明,只能在函数内部使用

1.3块级作用域

在大括号里面声明的变量(分支和循环),只能在大括号内部使用

1.4作用域示例

<script>
        //◆全局变量: 全局作用域
        let num = 10

        function fn() {
            //◆局部变量: 局部作用域(函数内部作用域)
            let age = 30
            console.log(age)
        }
        fn()

        for (let i = 1; i <= 10; i++) {
            //◆块级变量:块级作用域(只能在大括号内部使用)
            console.log(i)
        }
    </script>
***注意:函数的形参相当于在函数内部声明变量,属于局部变量

1.5块级作用域、函数作用域、词法作用域的区别

◆块级作用域与函数作用域描述的是,什么东西可以划分为变量的作用域

◆词法作用域描述的是,变量的查找规则

◆块级作用域 包含 函数作用域

◆词法作用域与块级作用域和函数作用域之间没有任何交集,他们从两个角度描述了作用域的规则

◆ES6之前采用的是函数作用域+词法作用域,ES6采用的是块级作用域+词法作用域

2.作用域链

默认情况下,js 代码处于全局作用域(0级),当我们声明一个函数的时候,就会开辟一个局部作用域(1级)。 函数里面也可以声明函数,就会又形成局部作用域(2级),以此类推就会形成作用域链。

变量在作用域链中的访问规则:就近原则

当你在某个作用域访问变量的时候,会先看当前作用域有没有声明。如果有,则访问当前作用域的变量;如果没有就找上级,上级也没有就继续往上,直到作用域的最顶端(0级);如果 0级 也没有,则程序会报错, xxx is not defined

<script>
        //全局作用域(0级)
        let num = 10

        function fn() {
            //局部作用域(1级)
            let num = 20
            console.log('1级作用域' + num)//20

            function fn1() {
                //局部作用域((2级)
                let num = 30
                console.log('2级作用域' + num)//30
            }
            fn1()
        }

        fn()

        console.log('0级作用域' + num)//10
    </script>

3.延长作用域链

执行环境的类型只有两种,全局和局部(函数),但是有些语句可以在作用域的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。简而言之,执行以下两个语句时,作用域链都会得到加强

  1. try-catch 语句的catch 块;会创建一个新的变量对象,包含的是被抛出的错误对象的声明
  1. with 语句,会将指定的对象添加到作用域链中