一文聊聊Javascript中的执行上下文

青灯夜游
Lepaskan: 2023-02-14 19:41:06
ke hadapan
2288 orang telah melayarinya

本篇文章带大家聊聊Javascript中的执行上下文,分享一个思考题,通过对思考题的分析,想必会对执行上下文有更加深入的理解。

一文聊聊Javascript中的执行上下文

在前面的几篇文章中,我们深入了解了关于执行上下文的三个重要成员:变量对象、作用域链和 this ,本篇文章是前四篇文章的的内容的集合,聚合分散的知识点,做一个简单的巩固。不知道有没有人是上一篇来的,我们的上一篇留下了一个思考题,通过对思考题的分析,想必会对执行上下文有更加深入的理解。

思考题

这里为了稍微将案例复杂化一点,做了一点点修改,但是并没有改变原题所考察的点。

function func(value){ getValue = function(){ console.log(value); }; return this } function getValue(){ console.log(5); } Func(1).getValue(); //为什么是1呢?
Salin selepas log masuk

具体执行分析

执行全局代码,创建全局执行上下文,全局上下文被压入执行上下文栈

ECStack = [ globalContext ];
Salin selepas log masuk
Salin selepas log masuk

初始化全局上下文

globalContext = { VO: { func: reference to function func(){}, getValue: reference to function getValue(){} }, Scope: [globalContext.VO], this: globalContext.VO //全局上下文 }
Salin selepas log masuk

初始化全局上下文同时创建了两个函数,因此也会保存他们父级作用域链在他们的内部属性 [[scope]] 内

func.[[scope]] = [ globalContext.VO ]; getValue.[[scope]] = [ globalContext.VO ];
Salin selepas log masuk

此时开始执行代码,执行到最后的语句时先执行 func 函数,也就创建按步骤 func 函数执行上下文:

  • 复制函数 [[scope]] 属性创建作用域链

  • 用 arguments 创建活动对象

  • 初始化活动对象

  • 将活动对象压入 checksfunccope 作用域链顶端。

  • 创建this,简单分析:MemberExpression 值为func,func是一个函数对象,理所当然是一个Reference ,其中它的 base value 是 EnvironmentRecord ,所以它的 this 值为 ImplicitThisValue(ref),返回值始终是 undefined ,非严格模式下,其值会被隐式转换为全局对象。

funcContext = { AO: { arguments: { // 数组 0: 1, length: 1 } }, Scope: [AO, globalContext.VO], this: undefined }
Salin selepas log masuk

可能有人会有疑问,func 里的 getValue 呢?,因为它并没有变量申明,因此他其实是一个属性的赋值操作,在后面运行时才会被执行。

创建函数执行上下文后压入执行上下文栈

ECStack = [ funcContext, globalContext ];
Salin selepas log masuk

函数开始执行,此时就是为什么最后输出是1的关键了,第一句赋值操作,那么就需要沿着执行上下文去找变量 getValue,那么我们就来看 funcContext 中的作用域,首先找到 funcContext.AO 显然并不存在 getValue 这一属性,那么沿着作用域链往上找,找到了globalContext.VO ,找到了 getValue ,这时候就会给全局作用域下的 getValue 属性重新赋值,赋的是一个函数的传新版本,也就重新创建了函数作用域,将这个全新的 getValue 函数的父级作用域链保存在它在他们的内部属性 [[scope]] 内:

getValue .[[scope]] = [ funcContext.AO, globalContext.VO ];
Salin selepas log masuk

然后才继续返回 this ,查找 funcContext 的 this ,即返回undefined;func 执行上下文出栈

ECStack = [ globalContext ];
Salin selepas log masuk
Salin selepas log masuk

继续执行Func(1).getValue(),前半部分返回了 undefined ,此时系统隐式转换为全局变量对象,从全局变量对象中找到 getValue 属性。这时候我们发现 getValue 早已不是当年那个少年,执行全新的 getValue 的函数执行上下文并入栈:

getValueContext = { AO: { arguments: { // 数组 length: 0 } }, Scope: [ AO, funcContext.AO, globalContext.VO ], this: undefined } ECStack = [ getValueContext, globalContext ];
Salin selepas log masuk

函数开始执行,发现她要输出value,沿着作用域去找,getValueContext.AO 中并没有这个属性, 继续往下找找到 funcContext.AO(注意!),在形参中 找到了 value 那么就输出对样的值,也就输出了1。

函数执行完毕,getValueContext 和 globalContext 相继出栈并销毁,代码运行完毕。

总结

本片以一个简单但又不简单的示例,将前面的四篇文章串联起来,完整地分析了JS代码执行时执行上下文的工作过程,希望大家对此能有更深的理解。但是,不知道有没有细心的同学发现,上面的示例中,执行 getValue 函数的过程中,由寻找属性 value的步骤(标记位置),那个时候 func 函数明明已经执行完毕了,他的执行上下文已经出栈了,为什么还能从他的执行上下文中找到 value 属性呢?这其实就是闭包产生的原理了,下一篇我们仍然用这个示例去学习闭包产生的原理。

【推荐学习:javascript高级教程

Atas ialah kandungan terperinci 一文聊聊Javascript中的执行上下文. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!