JS执行上下文与调用栈

1、执行上下文的分类
执行上下文主要分为三类:
全局上下文 —— 全局代码所处的环境,不在函数中的代码都在全局执行上下文中
函数上下文 —— 在函数调用时创建的上下文
Eval 执行上下文 —— 运行 Eval 函数中的代码时所创建的环境

2、全局上下文的创建和组成
当我们的 JS 脚本跑起来之后,第一个被创建的执行上下文就是全局上下文。
当我们的脚本里一行代码也没有的时候里,全局上下文里会比较干净,只有两个东西:
1.全局对象(浏览器里是 Window, Node 环境下是 Global)
2.this 变量。这里的 this ,指向的还是全局变量

每一个执行上下文都会经历这样一个生命周期
创建阶段 —— 执行上下文的初始化状态,此时一行代码都还没有执行,只是做了一些准备工作;
执行阶段 —— 逐行执行脚本里的代码。

创建阶段JS引擎做的事情:

  • 创建全局对象(Window 有了)
  • 创建 this ,并让它指向全局对象
  • 给变量和函数安排内存空间
  • 默认给变量赋值为undefined
  • 将函数声明放入内存 创建作用域链

执行上下文在执行阶段里其实始终是处在一个动态。

结合我们的上下文创建过程,你会知道,其实根本不存在任何的 “提升”,变量一直在原地。所谓的 “提升”,只是变量的创建过程(在上下文创建阶段完成)和真实赋值过程(在上下文执行阶段完成)的不同步带来的一种错觉。执行上下文在不同阶段完成的不同工作,才是 “变量提升 “的本质。

3、函数上下文的创建和组成
两者之间的不同主要体现在以下方面上:

  • 创建的时机 —— 全局上下文在进入脚本之初就被创建,而函数上下文则是在函数调用时被创建
  • 创建的频率 ——全局上下文仅在代码刚开始被解释的时候创建一次;而函数上下文由脚本里函数调用的多少决定,理论上可以创建无数次
  • 创建阶段的工作内容不完全相同 —— 函数上下文不会创建全局对象(Window),而是创建参数对象(arguments);
  • 创建出的 this不再死死指向全局对象,而是取决于该函数是如何被调用的 —— 如果它被一个引用对象调用,那么 this 就指向这个对象;否则,this的值会被设置为全局对象或者 undefined(在严格模式下)

4、调用栈
我们看到函数执行完毕后,其对应的执行上下文也随之消失了。这个消失的过程,我们叫它” 出栈 “—— 没错,在 JS 代码的执行过程中,引擎会为我们创建” 执行上下文栈 “(也叫调用栈)。

因为函数上下文可以有许多个,我们不可能保留所有的上下文。当一个函数执行完毕,其对应的上下文必须让出之前所占用的资源。因此上下文的建立和销毁,就对应了一个” 入栈 “和” 出栈 “的操作。当我们调用一个函数的时候,就会把它的上下文推入调用栈里,执行完毕后出栈,随后再为新的函数进行入栈操作。

作用域其实就是当前所处的执行上下文。

一般来说,函数出栈后,我们都没有办法再访问到函数内部的变量了。但闭包可不是这样。
在执行上下文的创建阶段,跟着被创建的还有作用域链!这个作用域链在函数中以内部属性的形式存在,在函数定义时,其对应的父变量对象就会被记录到这个内部属性里。闭包正是通过这一层作用域链的关系,实现了对父作用域执行上下文信息的保留。

注意!这里是沿着作用域链找,可不是沿着调用栈一层一层往上找哦!调用栈是在执行的过程中形成的,而作用域链可是在书写阶段就决定了。
5、原型编程范式
原型编程范式的核心思想就是利用实例来描述对象,用实例作为定义对象和继承的基础。在 JavaScript 中,原型编程范式的体现就是基于原型链的继承。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值