JavaScript 核心基础1

来源:互联网 发布:美国令人感动的 知乎 编辑:程序博客网 时间:2024/05/23 00:07

1. 编译原理

1.1 词法分析    程序 var a = 2; 被分解成 词法单元 var , a , = , 2 , ; ,1.2. 语法分析    词法单元 => AST(抽象语法树)    1.3. 代码生成    AST => 可执行代码

2. 编译介绍

2.1 引擎:负责整个js 编译和执行过程2.2 编译器:语法分析/代码生成2.3 作用域:查询变量+设置他们的访问权限

eg:

var a = 2

  1. 对于var a 编译器会询问作用域 是否有 a 存在同一个作用域中,若有,忽略该声明,继续编译;否则在当前域声明新变量,命名为a
  2. 对与 a=2 引擎 询问 作用域 是否存在一个a,存在则引用,不存在,就继续查找,找到了就把2赋值给a,没有则抛出一个异常。

(编译器查找a是否存在过的时候,实际是引擎进行LHS/RHS 查询)

a=2 对于a的查询 ——LHS(谁是赋值目标用)
console,log(a) 对于a的查询 ——RHS (赋值目标的源头的时候用)

RHS 查询的时候 从嵌套的作用域到全局作用于无法找到变量的时候 会抛出 ReferenceError异常

LHS 查询到 全局作用域 也没找到 会在全局创建一个该名称的变量 (非严格模式下)

ReferenceError:与作用域判别失败相关

TypeError:作用域判别成功,对结果的操作是不合理/非法的


3. 作用域

eg:

for(var i=0;i<10;i++){    console.log(i)}console.log(`outside=${i}`)

我们可以看出 我们想用块作用域来限制i;然而在for外 还是得到了i
这是var 绑定造成的

ES6中 我们可以用let/const 来避免这种情况
let用来声明变量,const来设置常量


4. 提升

var a = 2

编译器 实际是分成了2部分 var a 和 a=2

var a 是我们的定义声明 【编译阶段】

a = 2 是我们的赋值声明 ,它在此会等待【执行阶段】

所以我们这样就可以清楚的解释变量提升的问题

console.log(a);var a=2;// undefined

也就是 这里的var a 会先进入编译阶段;然后在执行阶段的时候 先console.log 后才会 a=2;
所以最后的结果是undefined

函数提升的问题类似

 foo(); var foo=function test(){    console.log(1); }// chrome: foo is not a function

报错可知:编译时 var foo ;执行的时候 foo() 报错foo 不是一个函数;因为这时候的foo还没有赋值成为一个函数
同时注意 这里的错误是typeError 而不是 ReferenceError
因为这里是对foo操作不合法造成的


5. 词法作用域与动态作用域

var a = 2;function foo() {  console.log( a );}function bar() {  var a = 3;  foo();}bar();
  1. 如果处于词法作用域。变量a首先在foo()函数中查找,没有找到。于是顺着作用域链到全局作用域中查找,找到并赋值为2。所以控制台输出2
  2. 如果处于动态作用域,同样地,变量a首先在foo()中查找,没有找到。这里会顺着调用栈在调用foo()函数的地方,也就是bar()函数中查找,找到并赋值为3。所以控制台输出3

    而 js 使用的是词法动态域

1 0
原创粉丝点击