一、作用域

  • 作用域是指程序源代码中定义变量的区域
  • 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限
  • JavaScript采用的是词法作用域 (lexical scoping) ,也就是静态作用域

    二、词法作用域(静态作用域)

  • 词法作用域也就是在词法阶段定义的作用域,也就是说词法作用域在代码书写时就已经确定了

  • 因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的
  • JavaScript 中其实只有词法作用域,并没有动态作用域,this 的执行机制让作用域表现的像动态作用域,this 的绑定是在代码执行的时候确定的 ```javascript // 词法作用域 var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); }

bar(); // 1   // 函数在哪里调用没有关系,变量的位置在编译的词法分析阶段就确定了。

  1. 代码分析:执行foo函数,首先在它的内部作用域查找是否有value这个局部变量,如果有就会使用这个局部变量,如果没有,根据书写的代码就会向上一层寻找,这时发现value变量存在是1,这就是词法作用域
  2. <a name="vtlcp"></a>
  3. # 三、动态作用域
  4. - 动态作用域的变量叫做动态变量。只要程序正在执行定义了动态变量的代码段,那么在这段时间内,该变量一直存在;代码段执行结束,该变量便消失。
  5. ```javascript
  6. // 动态作用域
  7. var value = 1;
  8. function foo() {
  9. console.log(value);
  10. }
  11. function bar() {
  12. var value = 2;
  13. foo();
  14. }
  15. bar(); // 2

代码分析:执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2,这就是动态作用域

四、思考题

  • 《JavaScript权威指南》中的例子
    1. var scope = "global scope";
    2. function checkscope(){
    3. var scope = "local scope";
    4. function f(){
    5. return scope;
    6. }
    7. return f();
    8. }
    9. checkscope();
    1. var scope = "global scope";
    2. function checkscope(){
    3. var scope = "local scope";
    4. function f(){
    5. return scope;
    6. }
    7. return f;
    8. }
    9. checkscope()();
    答案分析 :两段代码都会打印:local scope。原因也很简单,因为JavaScript采用的是词法作用域,函数的作用域基于函数创建的位置
    《JavaScript权威指南》答案:JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效