JavaScript的执行上下文、作用域和作用域链

JavaScript的执行过程

初始化全局对象

js引擎会在执行代码之前,会在堆内存中创建一个全局对象:Global Object(GO)

  • 该对象所有的作用域(scope)都可以访问;
  • 里面会包含Date、Array、String、Number、setTimeout、setInterval等等;
  • 其中还有一个window属性指向自己

执行上下文(Execution Contexts)

js引擎内部有一个执行上下文栈(Execution Context Stack,简称ECS),它是用于执行代码的调用栈

  • 那么现在它要执行谁呢?执行的是全局的代码块:
    • 全局的代码块为了执行会构建一个** Global Execution Context(GEC)**;
    • GEC会被放入到ECS中执行;
  • GEC被放入到ECS中里面包含两部分内容:
    • 第一部分:在代码执行前,在parser转成AST的过程中,会将全局定义的变量、函数等加入到GlobalObject中,但是并不会赋值;
      • 这个过程也称之为变量的作用域提升(hoisting)
    • **第二部分:**在代码执行中,对变量赋值,或者执行其他的函数;

认识VO对象(Variable Object)

每一个执行上下文会关联一个VO(Variable Object,变量对象),变量和函数声明会被添加到这个VO对象中。

当全局代码被执行的时候,VO就是GO对象了

全局代码执行过程(执行前)

在这里插入图片描述

全局代码执行过程(执行后)

在这里插入图片描述

函数如何被执行?

在执行的过程中执行到一个函数时,就会根据函数体创建一个函数执行上下文(Functional Execution Context,简称FEC),并且压入到EC Stack中。
_因为每个执行上下文都会关联一个VO,那么函数执行上下文关联的VO是什么呢? _

  • 当进入一个函数执行上下文时,会创建一个AO对象(Activation Object);
  • 这个AO对象会使用arguments作为初始化,并且初始值是传入的参数;
  • 这个AO对象会作为执行上下文的VO来存放变量的初始化;
函数的执行过程(执行前)

在这里插入图片描述

函数的执行过程(执行后)

在这里插入图片描述
在这里插入图片描述

var message = "Global Message";
var obj = {
  name: 'why',
}

function bar() {
  console.log("bar function");
  var address = "bar";
}
function foo(num) {
  var message = "Foo Message";
  bar();
  
  var age = 19;
  var height = 1.88;
  console.log("foo function");
}

foo(123);

14_函数互相调用-执行代码前.png
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

作用域和作用域链(Scope Chain)

当进入到一个执行上下文时,执行上下文也会关联一个作用域链(Scope Chain)。
作用域链是一个对象列表,用于变量标识符的求值;
当进入一个执行上下文时,这个**作用域链被创建,并且根据代码类型,添加一系列的对象; **
在这里插入图片描述
在这里插入图片描述

函数的嵌套内存表现图.png
当一个函数定义时就创建了作用域链,查找一个函数的作用域和创建有关。

作用域提升面试题

var n = 100;
function foo() {
  n = 200
}
foo();
console.log(n); // 200

![截屏2023-02-25 20.09.02.png](https://img-blog.csdnimg.cn/img_convert/02372671d54344dbe1b4ec4acd55077e.png#averageHue=#2f333f&clientId=ubb99cf0a-1314-4&from=drop&id=ub949fae6&name=截屏2023-02-25 20.09.02.png&originHeight=550&originWidth=853&originalType=binary&ratio=1.100000023841858&rotation=0&showTitle=false&size=292445&status=done&style=none&taskId=u3b4616d6-0231-4f57-bc68-66132bfc146&title=)

function foo() {
  console.log(n); //undefined
  var n = 200;
  console.log(n); //200
}
var n = 100;
foo();
var n = 100;
function foo1() {
  console.log(n);  // 100
}
function foo2() {
  var n = 200;
  console.log(n); // 200
  foo1();
}

foo2();
console.log(n); // 100
// 4. 
// 代码先解析,解析的时候会先定义 ao中存在,
var a = 100;
function foo() {
  console.log(a); // 100 ❌  undefined ✅
  return // 代码执行时
  var a = 100;
}
foo();
function foo() {
  var a = b = 100;
}
foo();
console.log(a) //报错 未定义
console.log(b)
// 开发中错误写法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

起伏羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值