JavaScript代码分为全局代码和函数(局部)代码。
全局执行上下文
在执行代码前将window定义为全局执行上下文。
对全局数据进行预处理:
- var定义的全局变量为undefined。添加为window属性。
- function定义的全局函数。提升为window方法。
- this赋值为window。
- 开始执行全局代码
console.log(a1)
console.log(a2)
console.log(this)
var a1 = 3
function a2(){
}
该段代码的执行相当于下面这段代码
console.log(window.a1)
window.a2()
console.log(this)
var a1 = 3
function a2(){
}
函数执行上下文
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象。
对局部数据进行预处理:
- 形参变量为赋值的实参,添加为上下文执行的属性。
- arguments按照实参列表赋值,添加为上下文属性。
- var定义的局部变量为undefined。添加为上下文的属性。
- function的声明函数赋值。添加为上下文的属性。
- this赋值(调用函数的对象)。
- 开始执行函数体代码。
函数执行上下文对象是一个虚拟的对象。
function fn(a1){
console.log(a1)
console.log(a2)
a3()
console.log(this)
console.log(arguments)
var a2 = 3
function a3(){
console.log('a3')
}
}
在fn的开始处可以访问a1, a2, a3, this, arguments。
其中arguments是伪数组。
栈中有一片区域专门给调用使用。即给console.log使用。
执行上下文栈
在全局代码执行前,JS引擎会创建一个栈来存储管理所有的执行上下文对象。在全局上下文(window)确定后,将其添加到栈中(压栈)。在函数执行上下文创建好之后,将其添加到栈中(压栈)。在当前函数执行完之后,将栈顶对象移除(出栈)。当所有代码执行完之后,栈中只剩下window。
var a = 10
var bar = function(x){
var b = 5
foo(x + b)
}
var foo = function(y){
var c = 5
console.log(a + c + y)
}
bar(10)
该代码总共产生了三个执行上下文对象。两个函数执行上下文对象。栈底的元素永远是window。
网友评论