• JS进阶作用域词法作用域和动态作用域


    词法作用域

    在介绍作用域的第一篇文章中说到编译器的第一个阶段是分词,词法作用域就是定义分词阶段的作用域,是由代码中变量作用域和块作用域的位置决定的,所以词法分析器在处理代码时会保持作用域不变。

    词法作用域只由函数被声明时所处的位置决定。

    function foo(a) {
      var b = a * 2;
      function foo2(c) {
        console.log(a,b,c)
      }
      foo2(b * 3);
    }
    foo(1); // 1 2 6
    

    上面的例子中有三个逐级嵌套的作用域:

    1. 第一级就是最外层的全局作用域,只有一个foo标识符。
    2. 第二级是foo创建的作用域,包含a、b和foo2三个标识符。
    3. 第三级时foo2创建的作用域,只有一个c标识符。

    作用域的嵌套结构和位置关系为JS引擎提供了查找标识符的信息。在上面的示例中,引擎要执行console.log(...)语句,并对a、b和c这3个变量引用,它首先要会从最内部的foo2作用域中查找,引擎找不到a,就会向上一级的foo作用域中查找,找到后对变量a进行了引用。b变量也是在foo作用域中找到。c变量在foo2作用域中找到。

    多层嵌套的作用域中可以定义同名标识符,内部的标识符会遮蔽外部的标识符,被称作“遮蔽效应”。

    var a = 1;
    function foo() {
      var a = 2;
      console.log(a); // 2
    }
    foo();
    

    全局变量会自动成为全局对象的属性,所以可以间接的通过引用全局对象的属性访问该变量。

    var a = 1;
    function foo() {
      var a = 2;
      console.log(window.a); // 1
    }
    foo();
    

    动态作用域

    JavaScript使用的是词法作用域,词法作用域的特点是它是在代码书写阶段定义的。动态作用域的特点是它是在代码运行时确定的,解释动态作用域是为了理解后面要说的this机制。

    动态作用域只由函数被调用时所处的位置决定。

    var a = 1;
    function foo() {
      console.log(a);
    }
    
    function foo2() {
      var a = 2;
      foo();
    }
    
    foo2(); // 1
    
    1. 如果处于词法作用域,变量a会先在foo函数中查找,没有找到。然后沿着作用域链到全局作用域中查找,找到了把1赋值给a,最终控制台打印1。

    2. 如果处于动态作用域,变量a同样先在foo函数中查找,没有找到。然后顺着调用栈到foo2中查找,找到了把2赋值给a,最终控制台打印2。

    总结一下就是,词法作用域是由函数声明位置决定,动态作用域由函数调用位置决定。

    优秀文章首发于聚享小站,欢迎关注!
  • 相关阅读:
    HTML5入门
    vue进阶:vuex(数据池)
    vue进阶:vue-router之导航守卫、路由元信息、路由懒加载
    vue进阶:vue-router(vue路由)的安装与基本使用
    vue进阶:vs code添加vue代码片段
    vue进阶:基于vue-cli创建项目(搭建手脚架)
    vue入门:(底层渲染实现render函数、实例生命周期)
    vue入门:(组件)
    webpack配置不同打包配置
    webpack开启本地服务器与热更新
  • 原文地址:https://www.cnblogs.com/yesyes/p/15351945.html
Copyright © 2020-2023  润新知