持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
1、代码被解析
代码被解析时V8引擎的parse模块会帮我们创建一个GlobalObject(GO)对象,里面包含,String, DateNumber, setTimeout, setInterval等等,并且还有一个window属性,属性值为this,指向这个对象(GO)
伪代码:
var GlobalObject = {
String: '类',
DateNumber: '类',
setTimeout: '类',
setInterval: '类',
......
window: GlobalObject
}
因为window拿到的还是这个对象,所以可以这样一直.window
console.log(window.window.window.window)
然后就是开始对代码进行解析
比如这串代码
var num1 = 20
var num2 = 30
var result = num1 +num2
function foo () {
}
创建GlobalObject对象后是这样的(伪代码)
var GlobalObject = {
String: '类',
DateNumber: '类',
setTimeout: '类',
setInterval: '类',
......
window: GlobalObject,
foo: undefined
num1 = undefined
num2 = undefined
result = undefined
}
总结:
js引擎会在执行代码之前,会在堆内存中创建一个全局对象:Global Object(GO)
该对象所有的作用域(scope)都可以访问
里面会包含Date、Array、String、Number、setTimeout、setInterval等等
其中还有一个window指向自己
2、运行代码
V8引擎为了执行代码,内部会有一个执行上下文栈(函数调用栈 Execution Context Stack, ECStack)
因为我们执行的是全局代码,为了全局代码能够正常执行,需要创建全局执行上下文(Global Execution Context,GEC)(全局代码被执行时才会创建)
附图解析
编辑
执行代码是下面代码从上往下依次执行执行
var num1 = 20
var num2 = 30
var result = num1 +num2
function foo () {
}
在执行num1代码时会找到VO,也就是GO,把GO里的num1属性值改成20,以此类推
在var声明的num1之前去console.log(num1)是不会报错的,而是undefined,就是因为GO对象,也就是所谓的作用域提升
总结
- 代码被解析,初始化全局对象go。go中会对变量的作用域进行提升,且默认初值为undefined
- 代码执行前,全局上下文(GEC中的vo指向go对象)进入执行上下文栈 (ECS)
- 代码依次执行,依次为go中的变量赋值。