全局执行上下文
- 在执行全局代码之前将window确定为全局执行上下文;
- 对全局数据进行预处理
- var定义的全局属性 ==> undefined,添加为window属性
- function声明的全局函数 ==> 赋值,添加为window方法
- 开始执行全局代码
函数执行上下文
- 在调用函数,准备执行函数体前,创建相应的函数执行上下文对象
- 对局部数据进行预处理
- 形参变量 ==> 赋值(实参) ==> 添加为函数执行上下文属性
- arguments ==>赋值(实参列表) ==> 添加为函数执行上下文属性
- var定义的局部属性 ==> undefined,添加为函数执行上下文属性
- function声明的函数 ==> 赋值,添加为函数执行上下文方法
- this ==> 赋值(调用函数的对象) ==>添加为函数执行上下文属性
- 开始执行函数体代码
执行上下文栈
- 在全局代码执行前,js引擎会创建一个栈来存放执行上下文对象;
- 在全局执行上下文(window)确定后,将其压入栈底;
- 在函数执行上下文创建后,将其压入栈中;
- 在当前函数执行完成后,将栈顶对象弹出;
- 在所有函数执行都执行完后,将全局执行上下文对象从栈顶弹出
作用域
- 编写代码时确定的一块静态代码段所在区域,主要分为全局作用域和函数作用域
- ES6之前没有块级作用域,es6之后新增了块级作用域
- 作用:用于隔离变量,防止不同作用于下的同名变量造成冲突
作用域与执行上下文的区别
- 区别1:
- 全局作用域之外,每个函数都会创建自己的作用域,作用域在定义函数时就确定了,而不是在调用是确定的;
- 全局执行上下文是在全局作用域确定后,JS代码马上执行前创建的;
- 函数执行上下文是在调用函数时,函数体执行之前创建的。
- 区别2:
- 作用域是静态的,只要函数定义好就一直存在,且不会改变;
- 上下文环境是动态的,调用函数时创建,函数调用结束后就会被释放。
联系
- 执行上下文从属于所在的作用域。
- 全局执行上下文 ==> 全局作用域
- 函数执行上下文 ==> 函数作用域
面试题
var x = 10
function fn(){
console.log(x)
}
function show(f){
var x = 20
f()
}
show(fn)
var fn = function(){
console.log(fn)
}
fn()
var obj = {
fn2:function(){
console.log(fn2)
}
}
obj.fn2()