zoukankan      html  css  js  c++  java
  • JavaScript深入之词法作用域和动态作用域

    作用域

    作用域是指程序源代码中定义变量的区域。

    作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。

    JavaScript 采用词法作用域,也就是静态作用域。

    静态作用域与动态作用域

    因为Javascript采用的是词法作用域,所以它的函数的作用域在函数定义的时候就决定了。

    而与词法作用域相对的是动态作用域,它的函数的作用域是在函数调用的时候才决定的。

    让我们认真看个例子就能明白之前的区别:

    var value = 1;
    
    function foo(){
      console.log(value)
    }
    
    function bar(){
      var value = 2;
      foo();
    }
    
    bar();
    
    // 结果是?
    
    

    假设javascript采用静态作用域,让我们分析下执行过程:

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

    假设javascript采用动态作用域,让我们分析下执行过程:

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

    前面我们已经说了,javascript采用的是静态作用域,所以这个例子的结果是1。

    动态作用域

    也许你会好奇什么语言是动态作用域?

    bash 就是动态作用域,不信的话,把下面的脚本存成例如 scope.bash,然后进入相应的目录,用命令行执行 bash ./scope.bash,看看打印的值是多少。

    value =1 ;
    function foo(){
      echo $value
    }
    function bar(){
      local value = 2;
      foo
    }
    bar
    

    思考题

    最后,让我们看一个《javascript权威指南》中的例子:

    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()();
    
    

    猜猜两段代码各自执行结果是多少?

    这里直接告诉大家结果,两段代码都会打印: local scope;

    原因也很简单,因为javascript采用的是词法作用域,函数的作用域基于函数创建的位置。

    而引用《javascript权威指南》的回答是:

    javascript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数f()定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行f()时依然有效。

    参考文章:https://github.com/mqyqingfeng/Blog/issues/2

  • 相关阅读:
    Ext JS学习第三天 我们所熟悉的javascript(二)
    Ext JS学习第二天 我们所熟悉的javascript(一)
    Ext JS学习第十七天 事件机制event(二)
    Ext JS学习第十六天 事件机制event(一)
    Ext JS学习第十五天 Ext基础之 Ext.DomQuery
    Ext JS学习第十四天 Ext基础之 Ext.DomHelper
    Ext JS学习第十三天 Ext基础之 Ext.Element
    Ext JS学习第十天 Ext基础之 扩展原生的javascript对象(二)
    针对错误 “服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF” 的原因分析
    C# 使用HttpWebRequest通过PHP接口 上传文件
  • 原文地址:https://www.cnblogs.com/zhouyangla/p/8327412.html
Copyright © 2011-2022 走看看