词法作用域和动态作用域

181 阅读2分钟

什么是作用域?

作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。也就是确定当前执行代码对变量的访问权限。

- LHS和RHS对变量两种查找操作

字面意思,left hand side right hand side, 是一个赋值操作的左侧和右侧。 如果查找的目的是对变量进行赋值,那么就会使用 LHS 查询;

  • lhs var a = 2; 不管 = 2 赋给谁,只想找到一个容器赋值 如果目的是获取变量的值,就会使用 RHS 查询。 rhs retrieve his source value 取到它的源值
  • console.log(a),a就是rhs引用,并没有赋予任何值,只是找到它
    function foo(a) {
        var b = a;
        return a + b;
    }
    var c = foo( 2 );
  • 找出所有的 LHS 查询 (这里有 3 处!)c = ..;、a = 2(隐式变量分配)、b = ..
  • 找出所有的 RHS 查询 (这里有 4 处!) foo(2..、= a;、a ..、.. b

静态作用域?

由写代码期间函数所声明的位置来定义

    var value = 1;
    function foo() {
        console.log(value);
    }
    function bar() {
        var value = 2;
        foo();
    }
    bar();

// 结果是 ??? 执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。

动态作用域?

函数的作用域是在函数调用的时候才决定的

  • 假设JavaScript采用动态作用域,让我们分析下执行过程: 执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2。
    var scope = "global scope";
    function checkscope(){
        var scope = "local scope";
        function f(){
            return scope;
        }
        return f();
    }
    checkscope();

    var scope = "global scope";
    function checkscope(){
        var scope = "local scope";
        function f(){
            return scope;
        }
        return f;
    }
    checkscope()();

因为JavaScript采用的是词法作用域,函数的作用域基于函数创建的位置。

结果都是“local scope”

但是这两个也是有区别的,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出

  • 第一个是先checkscope压栈,在f压栈,然后再弹栈
  • 第二个checkscope压栈,执行完,弹栈,再f压栈,然后再弹栈