面试再探讨:浏览器中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执行完毕,进行弹栈,在这我们能够理解,如果不弹栈,见到一个我们就需要创建一个执行上下文对象,长此以往,就会造成栈溢出

小结

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

相关推荐
fruge4 分钟前
纯css制作声波扩散动画、js+css3波纹催眠动画特效、【css3动画】圆波扩散效果、雷达光波效果完整代码
javascript·css·css3
CXDNW11 分钟前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
neter.asia13 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫13 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
光影少年33 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_34 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891136 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾37 分钟前
前端基础-html-注册界面
前端·算法·html
Rattenking37 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
Dragon Wu39 分钟前
前端 Canvas 绘画 总结
前端