美文网首页
深入理解js系列一作用域是什么?

深入理解js系列一作用域是什么?

作者: 神刀 | 来源:发表于2018-03-10 11:28 被阅读23次

    title: 深入理解js系列一作用域是什么?
    date: 2018-02-06 02:15:59
    tags:

    • 深入理解js系列
    • 作用域
      categories: JavaScript

    作用域是什么?

    变量的作用域到底是如何在js中工作的?

    js是解释型语言而无法编译吗?

    什么是词法作用域?

    RHS查询与LHS查询?

    理解作用域

    js中的作用域可以理解为一套定义的规则,用来管理js引擎根据标识符名称进行变量查找,并确定当前执行代码对这些变量的访问权限。

    编译原理

    要想深入理解js的作用域,我们必须得先知道js事实上是一门编译型语言(动态编译)-- js引擎实际上是动态编译程序然后立即执行。与传统编译语言在构建前编译不同的是:js的编译发生在代码执行前(有时是执行中)的很短时间内,而且编译完通常就会马上执行它。另外,对比传统编译,js引擎在语法分析和代码生成阶段有特定的步骤对运行性能进行优化。这也是后面会谈到的eval()with() 影响运行效率的原因。

    编译的三个步骤

    我们先来看看在传统编译语言中,一段源程序在执行前通常要经历的三个步骤,js作为一门动态编译语言,同样也会经历这些步骤:

    1. 分词/词法分析(将源代码分解成词法单元)
    2. 解析/语法解析(转换为一棵由元素逐级嵌套组成代表程序语法的抽象语法树AST)
    3. 代码生成(将AST转换为可执行代码)

    在js中,js引擎负责整个js程序的编译和执行过程,编译器负责语法分析以及代码生成。

    js引擎做了什么?

    当遇到var a = 2这段程序,js引擎做了什么?

    1. 首先编译器会将这段代码分解成词法单元
    2. 编译器再将词法单元解析成一个树结构
    3. 编译器开始进行代码生成
      1. 遇到var a,查询作用域链是否有变量a:
        。 有a:跳过继续编译
        。 无a:在当前作用域声明一个变量a
      2. 为引擎生成运行时所需代码
    4. 引擎查询作用域链是否存在变量a:
      。存在:使用变量a执行赋值操作
      。不存在:抛出一个异常

    可以看出,变量的赋值操作会执行两个动作:
    一个由编译器在编译时处理,另一个由引擎在运行时处理。

    RHS查询与LHS查询?

    LHS查询:查找变量的容器本身(a=1)
    RHS查询: 查找变量的值(console.log(a))

    function foo(a){
        console.log(a)
    }
    foo(2) //RHS查询
    // 将2作为参数传给foo函数,给参数a隐式地分配值时进行了一次LHS查询
    

    作用域嵌套

    异常

    在作用域中找不到变量

    在作用域中找变量

    总结:
    不成功的RHS引用抛ReferenceError

    。。。
    未完待续

    相关文章

      网友评论

          本文标题:深入理解js系列一作用域是什么?

          本文链接:https://www.haomeiwen.com/subject/lvbvfftx.html