Appearance
JavaScript引擎解析代码的执行顺序
- 检查通篇语法,如果有错误则直接抛出(不执行任何代码),没有则进行预编译;
- 预编译;
- 解释一行代码,执行一行;
- 函数声明整体提升,变量声明只提升声明,赋值不提升(所以存在先声明变量,后赋值);
暗示全局变量(imply global variable)
没有用var声明的变量是全局变量,在全局环境下,变量和方法都是挂载到window对象上,相当于window对象的属性和方法;
- 思考:为什么window.c一个不存在的属性是undefined,而直接打印c一个不存在的属性报错()。因为window.c属于对象语法性质;
- 在全局声明变量和函数,都是作为window对象的属性。但是二者并不是同一个东西,window中的属性与声明的变量存在映射的关系,所以二者能够同时随之改变;二者在内存中存放的位置都不同,变量存放在栈内存中,window对象存放在堆内存中;
AO(activation object)函数执行期上下文
在AO中js引擎编译步骤
- 寻找函数的形参和变量声明
- 实参值赋给形参
- 寻找函数声明
- 执行函数
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引擎预编译的步骤
- 寻找变量声明
- 寻找函数声明
- 执行代码
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(){}的指针,当这个对象被定义的时候,匿名函数才会被定义。反过来说,如果单纯的提升一个匿名函数,这个匿名函数也没有指向,对于代码整体来说没有任何意义。预编译去寻找变量的目的是:这次执行先要确定有哪些变量,然后才好去赋值。