JavaScript深刻系列第七篇,结合以前所讲的四篇文章,以权威指南的demo为例,具体讲解当函数执行的时候,执行上下文栈、变量对象、做用域链是如何变化的。git
在《JavaScript深刻之执行上下文栈》中讲到,当 JavaScript 代码执行一段可执行代码(executable code)时,会建立对应的执行上下文(execution context)。github
对于每一个执行上下文,都有三个重要属性:面试
而后分别在《JavaScript深刻之变量对象》、《JavaScript深刻之做用域链》、《JavaScript深刻之从ECMAScript规范解读this》中讲解了这三个属性。闭包
阅读本文前,若是对以上的概念不是很清楚,但愿先阅读这些文章。app
由于,这一篇,咱们会结合着全部内容,讲讲执行上下文的具体处理过程。函数
在《JavaScript深刻之词法做用域和动态做用域》中,提出这样一道思考题:post
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();复制代码
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();复制代码
两段代码都会打印'local scope'。虽然两段代码执行的结果同样,可是两段代码究竟有哪些不一样呢?ui
紧接着就在下一篇《JavaScript深刻之执行上下文栈》中,讲到了二者的区别在于执行上下文栈的变化不同,然而,若是是这样笼统的回答,依然显得不够详细,本篇就会详细的解析执行上下文栈和执行上下文的具体变化过程。this
咱们分析第一段代码:spa
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();复制代码
执行过程以下:
1.执行全局代码,建立全局执行上下文,全局上下文被压入执行上下文栈
ECStack = [
globalContext
];复制代码
2.全局上下文初始化
globalContext = {
VO: [global, scope, checkscope],
Scope: [globalContext.VO],
this: globalContext.VO
}复制代码
2.初始化的同时,checkscope 函数被建立,保存做用域链到函数的内部属性[[scope]]
checkscope.[[scope]] = [
globalContext.VO
];复制代码
3.执行 checkscope 函数,建立 checkscope 函数执行上下文,checkscope 函数执行上下文被压入执行上下文栈
ECStack = [
checkscopeContext,
globalContext
];复制代码
4.checkscope 函数执行上下文初始化:
同时 f 函数被建立,保存做用域链到 f 函数的内部属性[[scope]]
checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope: undefined,
f: reference to function f(){}
},
Scope: [AO, globalContext.VO],
this: undefined
}复制代码
5.执行 f 函数,建立 f 函数执行上下文,f 函数执行上下文被压入执行上下文栈
ECStack = [
fContext,
checkscopeContext,
globalContext
];复制代码
6.f 函数执行上下文初始化, 如下跟第 4 步相同:
fContext = {
AO: {
arguments: {
length: 0
}
},
Scope: [AO, checkscopeContext.AO, globalContext.VO],
this: undefined
}复制代码
7.f 函数执行,沿着做用域链查找 scope 值,返回 scope 值
8.f 函数执行完毕,f 函数上下文从执行上下文栈中弹出
ECStack = [
checkscopeContext,
globalContext
];复制代码
9.checkscope 函数执行完毕,checkscope 执行上下文从执行上下文栈中弹出
ECStack = [
globalContext
];复制代码
第二段代码就留给你们去尝试模拟它的执行过程。
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();复制代码
不过,在下一篇《JavaScript深刻之闭包》中也会说起这段代码的执行过程。
《JavaScript深刻之从ECMAScript规范解读this》
本文写的太好,给了我不少启发。感激涕零!
JavaScript深刻系列目录地址:github.com/mqyqingfeng…。
JavaScript深刻系列预计写十五篇左右,旨在帮你们捋顺JavaScript底层知识,重点讲解如原型、做用域、执行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、继承等难点概念。
若是有错误或者不严谨的地方,请务必给予指正,十分感谢。若是喜欢或者有所启发,欢迎star,对做者也是一种鼓励。