Open hzzzzzzzq opened 2 years ago
在[《JavaScript 深入之执行上下文栈》]()中提到,当 JavaScript 代码执行代码时,就会创建一个执行上下文。
对于执行上下文,都有三个重要属性:
分别单独介绍了三个属性 - [《JavaScript 深入之变量对象》]()、[《JavaScript 深入之作用域链》]()、[《JavaScript 深入之 this》]()。
我们在上面的文章中,不止一次提到过执行上下文这个东西,然后每次都是分开介绍的,并不完全,现在我们就来整合一下执行上下文吧。
我们直接给出一个例子吧,然后来看看什么是执行上下文吧。
var name = 'hzq'; function checkName() { var name = 'hzzzzzzzq'; function fn() { return name; } return fn(); } console.log(checkName()); // hzzzzzzzq
1. 执行全局代码,创建全局上下文,并压入执行上下文栈
ECStack = [globalContext];
2. 全局上下文初始化,同时创建 checkName 函数,保存作用域链到函数内部属性 [[scope]]
checkName
[[scope]]
globalContext = { VO: [global], Scope: [globalContext.VO], this: globalContext.VO, }; checkName.[[scope]] = [ globalContext.VO ];
3. 执行 checkName 函数,创建函数上下文,并压入栈
ECStack = [checkNameContext, globalContext];
4. checkName 函数执行上下文初始化: | 这时候 fn 函数也被创建,保存 [[scope]]
fn
checkNameContext = { AO: { arguments: { length: 0, }, name: undefined, fn: reference to function fn() {} }, Scope: [AO, globalContext.VO], this: undefined }; // fn 函数保存 [[scope]] fn.[[scope]] = [ checkNameContext.AO, gloablContext.VO ]
5. 执行 fn 函数,创建上下文,压入栈
ECStack = [fnContext, checkNameContext, globalContext];
6. fn 函数执行上下文初始化
fnContext = { AO: { arguments: { length: 0, }, }, Scope: [AO, checkNameContext.AO, globalContext.VO], this: undefined, };
7. fn 通过作用域链查找 name 属性,并返回
name
8. fn 函数指向完毕,出栈
9. checkName 函数执行完毕,出栈
10. 继续执行其他全局代码,直到其他代码执行完毕,全局上下文出栈
var name = 'hzq'; function checkName() { var name = 'hzzzzzzzq'; function fn() { return name; } return fn; } checkName()(); // hzzzzzzzq // 等价于 let fn = checkName(); fn();
我们直接来看看例子二与例子一的不同点。
5. checkName 函数执行完毕,出栈
6. 执行 fn 函数,创建上下文,压入栈
ECStack = [fnContext, globalContext];
7. fn 函数执行上下文初始化
8. fn 函数执行完毕,出栈
9. 执行全局其他代码,执行完毕,全局上下文出栈
是不是很简单呢?
JavaScript 深入之执行上下文
在[《JavaScript 深入之执行上下文栈》]()中提到,当 JavaScript 代码执行代码时,就会创建一个执行上下文。
对于执行上下文,都有三个重要属性:
分别单独介绍了三个属性 - [《JavaScript 深入之变量对象》]()、[《JavaScript 深入之作用域链》]()、[《JavaScript 深入之 this》]()。
我们在上面的文章中,不止一次提到过执行上下文这个东西,然后每次都是分开介绍的,并不完全,现在我们就来整合一下执行上下文吧。
执行上下文 - 例子一
我们直接给出一个例子吧,然后来看看什么是执行上下文吧。
执行过程
1. 执行全局代码,创建全局上下文,并压入执行上下文栈
2. 全局上下文初始化,同时创建
checkName
函数,保存作用域链到函数内部属性[[scope]]
3. 执行 checkName 函数,创建函数上下文,并压入栈
4. checkName 函数执行上下文初始化: | 这时候
fn
函数也被创建,保存[[scope]]
[[scope]]
属性5. 执行
fn
函数,创建上下文,压入栈6.
fn
函数执行上下文初始化7.
fn
通过作用域链查找name
属性,并返回8. fn 函数指向完毕,出栈
9.
checkName
函数执行完毕,出栈10. 继续执行其他全局代码,直到其他代码执行完毕,全局上下文出栈
执行上下文 - 例子二
执行过程 - 变化点
我们直接来看看例子二与例子一的不同点。
5.
checkName
函数执行完毕,出栈6. 执行
fn
函数,创建上下文,压入栈7.
fn
函数执行上下文初始化8.
fn
函数执行完毕,出栈9. 执行全局其他代码,执行完毕,全局上下文出栈
是不是很简单呢?