Skip to content

JavaScript引擎解析代码的执行顺序

  1. 检查通篇语法,如果有错误则直接抛出(不执行任何代码),没有则进行预编译;
  2. 预编译;
  3. 解释一行代码,执行一行;
  4. 函数声明整体提升,变量声明只提升声明,赋值不提升(所以存在先声明变量,后赋值);

暗示全局变量(imply global variable)

没有用var声明的变量是全局变量,在全局环境下,变量和方法都是挂载到window对象上,相当于window对象的属性和方法;

  1. 思考:为什么window.c一个不存在的属性是undefined,而直接打印c一个不存在的属性报错()。因为window.c属于对象语法性质;
  2. 在全局声明变量和函数,都是作为window对象的属性。但是二者并不是同一个东西,window中的属性与声明的变量存在映射的关系,所以二者能够同时随之改变;二者在内存中存放的位置都不同,变量存放在栈内存中,window对象存放在堆内存中;

AO(activation object)函数执行期上下文

在AO中js引擎编译步骤

  1. 寻找函数的形参和变量声明
  2. 实参值赋给形参
  3. 寻找函数声明
  4. 执行函数
js
function test(a, b) {
  console.log(a); // 1
  c = 0;
  var c;
  a = 5;
  b = 6;
  console.log(b); // 6
  function b(){};
  function d(){};
  console.log(b); // 6
}
test(1);

// 预编译
AO = {
   a:undefined,
   ---> 1
    ---> 5
   b:undefined,
   ---> function b(){}
    ---> 6
   c:undefined,
     ---> 0
   d:function d(){}
}

GO(global object)全局对象,全局执行期上下文

GO中js引擎预编译的步骤

  1. 寻找变量声明
  2. 寻找函数声明
  3. 执行代码

    GO全局对象与window对象相等 GO===window

js
console.log(a, b); // function a(){}  undefined
function a(){};
var b = function(){};

// 预编译
GO = {
	b:undefind,
  --> function(){}
  a:function a(){},
}

预编译的存在的意义

GO和AO的定义是让JS引擎看的,预编译是为了让JS引擎能够更好的去解析代码。上面的例子,在JS引擎执行脚本语言的时候,才将{}赋值给obj变量,obj变量内部存放是的指向{}的指针,obj的name属性存放着指向function(){}的指针,当这个对象被定义的时候,匿名函数才会被定义。反过来说,如果单纯的提升一个匿名函数,这个匿名函数也没有指向,对于代码整体来说没有任何意义。预编译去寻找变量的目的是:这次执行先要确定有哪些变量,然后才好去赋值。