面试再探讨:浏览器中js的执行与机制

前言

上回我们深入了解了作用域、作用域链,那么今天我们再次深入探讨一下浏览器中js的执行与机制的底层原理,聊聊调用栈作用域链这一全过程,全局执行上下文函数执行上下文eval执行上下文,这个创建、删除过程又是通过一个什么数据结构完成的呢?

面试题引入

在此之前先给各位安利一款百度最近刚刚开源的插件,vs中或者其他idea类全家桶都能够安装,comate.baidu.com/index.html?... ,你也可以之前通过vs插件搜索baiducomate,真的很智能,你们可以去试试。

ini 复制代码
function bar(params) {
    console.log(myName);
}

function foo(params) {
    var myName = 'Tom'
    bar();
}

var myName = 'Jerry';

foo();

题目很简单,但是需要你真正理解底层的执行过程

变量提升(发生在编译阶段)

在 JavaScript 中,变量提升是指在代码执行之前,变量和函数声明会被提升到当前作用域的顶部。 这意味着即使在声明之前使用变量,也不会导致错误,但此时变量的值是 undefined。 需要注意的是,只有声明会被提升,赋值操作不会被提升。

ini 复制代码
console.log(x); // 输出 undefined 
var x = 5;

那么这个代码事实上长这样

ini 复制代码
var x
console.log(x); 
x = 5;

包含函数的变量提升

javascript 复制代码
console.log(myFunction); // 输出函数定义

function myFunction() {
  console.log("函数被调用");
}

在js引擎的眼中的执行上下文创建过程

之前我们谈过GO(全局作用域对象)、AO对象,那么其实每一个执行上下文中都有一个变量环境和一个词法环境,变量环境中放var的声明变量和函数声明,词法环境中放let和const声明的变量。接下来回到这个面试题引入部分

ini 复制代码
function bar(params) {
    console.log(myName);
}

function foo(params) {
    var myName = 'Tom'
    bar();
}

var myName = 'Jerry';

foo();

分析过程

这些创建的GO\AO对象都存放在哪里呢?

  • 栈结构: 特殊的数组,先进后出
  • 调用栈: js引擎用来追踪函数调用关系的
  • 栈溢出: 调用栈超出内存限制 代码从上往下执行,在全局中首先创建GO对象,也就是全局执行上下文,存放在栈中,放入栈底,全局上下文中有变量环境与词法环境,代码从上往下执行就会发现声明了bar函数和foo函数以及myName变量。图中(全局可执行对象打错了,应该是全局执行上下文!)

紧接着就执行代码,调用foo函数,既然要调用foo函数,首先就需要对foo函数进行预编译,创建AO对象,放入栈中,变量声明首先值为undefined,然后赋值为Tom

紧接着执行调用bar函数,此时需要对bar函数进行预编译,创建AO对象

打印myName,那么在这里就发现了bar执行上下文中没有myName,那么接下来这个属性去哪里找呢?我们都知道,执行上下文中会从词法环境开始找,然后再找变量环境,如果都没有呢?是顺着栈顶向下找吗?答案是否定的。事实上每一个执行上下文中,都存有一个outer属性,这个outer属性的规则是:我的词法作用域(在函数定义时所在的作用域)在哪里,我就指向哪里。那么在bar中,bar的词法作用域存在于全局执行上下文中,那么这个outer就指向全局执行上下文,在自己的bar执行上下文对象中没有找到myName属性,就去全局中找,全局中myName属性值为Jerry,前面的图忘记加上了,在调用foo之前,已经执行过对Myname属性赋值的语句了,这也是一个执行代码的过程

接下来bar函数执行完毕,需要对bar的执行上下文进行释放,弹栈,然后foo执行完毕,进行弹栈,在这我们能够理解,如果不弹栈,见到一个我们就需要创建一个执行上下文对象,长此以往,就会造成栈溢出

小结

本次内容虽然很简单,但是极易出错,知识点都是代码的底层逻辑,理解透彻以后才能在面试时对答如流从容面对。再次多提一下,在执行上下文中的查找过程,是从词法环境查找然后再往变量环境中查找,每一个环境又是一个小的栈结构,也是从栈顶开始向栈底查找,如图所示:

相关推荐
Mr_Xuhhh1 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
永乐春秋2 小时前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿2 小时前
【前端】CSS
前端·css
ggdpzhk2 小时前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
小曲曲3 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•4 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS5 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜6 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点6 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow6 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js