美文网首页
上卷 第一部分 第一章 作用域是什么

上卷 第一部分 第一章 作用域是什么

作者: nymlc | 来源:发表于2018-04-12 09:35 被阅读0次

前言

作用域就是一套描述在何处以及如何查找变量的规则。

编译原理

JavaScript通常被称作动态解析执行语言,不过其实它是编译语言。它与传统的编译语言不一样的是它不是提前编译的。它大部分情况下发生在执行前的几微秒,甚至更短。
传统的编译语言三步骤

  1. 分词/词法分析
    这个过程是将字符串分解成有意义的代码块(词法单元)。
    分词和词法分析区别在于词法单元的识别是有状态还是无状态。比如判断a是否是独立的词法单元还是别的词法单元的一部分调用的就是有状态解析规则,这个就是词法分析

var a = 2;会被分解成var、a、=、2、;。空格是否是词法单元在于它在此语言是否有意义

  1. 解析/语法分析
    就是将词法单元流(数组)转成由元素逐级嵌套所组成的代表了程序语法结构的树(AST,Abstract Syntax Tree,抽象语法树)
  2. 代码生成
    将AST转换成可执行的代码过程就是代码生成。比如就是有某种方法可以将var a = 2;的AST转换成一组机器指令,用于创建一个a的变量(分配内存什么的),然后将值存在a中。
    JavaScript引擎在语法分析和代码生成阶段有特定的步骤对运行性能进行优化,包括对冗余元素进行优化。它不会有很多时间用于优化,因为JavaScript的编译过程不是发生在构建之前。他用了很多方法保证性能(比如JIT,用于延迟编译甚至重编译)

作用域

三个角色

  1. 引擎:负责整个程序的编译和运行
  2. 编译器:负责词法分析、语法分析和代码生成
  3. 作用域:负责变量的查询规则,确定执行的代码对变量的访问

对var a = 2;的处理
编译器遇到var a就会询问作用域是否有a变量存在当前作用域之中,若是则忽略该声明继续编译,否则要求作用域在当前作用域之中声明一个a变量。然后编译器会进行代码生成来执行a = 2;这个赋值操作。引擎会询问作用域当前作用域是否存在a变量(虽然之前已经询问过),若是引擎就会使用此变量,否则就往上层继续寻找,找到的话就会将2赋值给啊,未找到的话就会抛出异常
代码执行过程LHS、RHS
若是查找变量用于赋值(比如=或者传参)那么该查找为LHS,若是用于引用那么则是RHS

function foo(a) {
var b = a;
return a + b;
}
var c = foo(2);

  1. foo(2):RHS查询
  2. foo(a):LHS查询
  3. = a:RHS查询
  4. var b = :LHS查询
  5. return a...:RHS查询
  6. + b:RHS查询
  7. c = ...:LHS查询

作用域嵌套

块(catch、with)或者函数嵌套就会发生作用域嵌套,LHS与RHS查询会逐层往上,直到全局作用域

异常

若是第一次RHS查询失败就是说明查询的变量未声明,引擎会抛出ReferenceError异常
若是LHS呢会在全局作用域创建一个该变量(该是在非严格模式之下,严格模式下抛出ReferenceError异常)
若是对变量进行不合理操作比如引用null的属性神马的,那么会抛出TypeError异常

总结

总的而言,就是变量的声明在代码执行之前就好了,之后对变量的查询就是RHS和LHS

相关文章

网友评论

      本文标题:上卷 第一部分 第一章 作用域是什么

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