JavaScript深切系列第七篇,连系之前所讲的四篇文章,以威望指南的demo为例,细致解说当函数实行的时刻,实行上下文栈、变量对象、作用域链是怎样变化的。
媒介
在《JavaScript深切之实行上下文栈》中讲到,当 JavaScript 代码实行一段可实行代码(executable code)时,会建立对应的实行上下文(execution context)。
关于每一个实行上下文,都有三个主要属性:
变量对象(Variable object,VO)
作用域链(Scope chain)
this
然后分别在《JavaScript深切之变量对象》、《JavaScript深切之作用域链》、《JavaScript深切之从ECMAScript范例解读this》中解说了这三个属性。
浏览本文前,假如对以上的观点不是很清晰,愿望先浏览这些文章。
由于,这一篇,我们会连系着一切内容,讲讲实行上下文的细致处置惩罚历程。
思索题
在《JavaScript深切之词法作用域和动态作用域》中,提出如许一道思索题:
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’。虽然两段代码实行的效果一样,然则两段代码终究有哪些差别呢?
紧接着就鄙人一篇《JavaScript深切之实行上下文栈》中,讲到了二者的区分在于实行上下文栈的变化不一样,但是,假如是如许笼统的回复,依旧显得不够细致,本篇就会细致的剖析实行上下文栈和实行上下文的细致变化历程。
细致实行剖析
我们剖析第一段代码:
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 函数实行上下文初始化:
复制函数 [[scope]] 属性建立作用域链,
用 arguments 建立运动对象,
初始化运动对象,即到场形参、函数声明、变量声明,
将运动对象压入 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 步雷同:
复制函数 [[scope]] 属性建立作用域链
用 arguments 建立运动对象
初始化运动对象,即到场形参、函数声明、变量声明
将运动对象压入 f 作用域链顶端
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深切系列目次地点:https://github.com/mqyqingfeng/Blog。
JavaScript深切系列估计写十五篇摆布,旨在帮人人捋顺JavaScript底层学问,重点解说如原型、作用域、实行上下文、变量对象、this、闭包、按值通报、call、apply、bind、new、继续等难点观点。
假如有毛病或许不严谨的处所,请务必赋予斧正,非常谢谢。假如喜好或许有所启示,迎接star,对作者也是一种勉励。