ECS&闭包

执行上下文

  • 全局读写变量
  • 函数内部读写变量
  • eval('str')

全局执行上下文

执行上下文广义上可以分为两块,Lexical Environment 和 This Bindbing

Lexical Environment

组成:

  • 全局对象
  • 全局scope
  • outer: null

全局执行上下文中的outer 为 null 全局对象:

  • 浏览器环境下是window对象
This Binding

当你使用this的时候,其实就是读this binding这个区域存储的值

对于全局执行陕西该文(GC),This Binding指向全局对象,浏览器环境下是window对象

执行上下文的创建过程

别急,先想清楚什么是执行上下文创建流程

执行上下文的作用是微程序提供查找变量的地方,因此,我们可以想到,所谓执行上下文的流程,就是将程序中的变量声明进行处理,存储在执行上下文里

可以简单的将其划分为下面几个步骤:

  • 处理声明
  • 检查重复定于
  • 创建绑定
1、处理声明
  • 找到所有的全局中的var声明,找到所有的 顶级 全局函数 声明(注意和函数表达式进行区分),将其记录在全局对象中
csharp 复制代码
(function foo(){}); // 不符合 函数表达式
if(true) {
    function who() {}
}
function bar() {}; // 符合
  • 找到顶级的let const class,记录在全局scope
2、检查重复定义

检查全局scope中是否含有重复声明的变量?有则报错

需要注意的是,这里还会检查全局scope和 全局对象中是否含有冲突

javascript 复制代码
console.log('hello world'); // 不会运行打印 
// 会抛出错误:Uncaught SyntaxError: Identifier 'a' has already been declared
// 因为检查重复是在 执行上下文的创建过程进行的,还没到执行的步骤就报错了
var a = 0;
let a = 1;
3、创建绑定

这一步是对变量进行初步赋值

  • var声明的变量被赋值为undefined
  • 函数声明会 创建函数对象,然后让该变量指向该对象

函数对象 js函数的本质是一种特殊的对象,含有一个特殊的prototype属性,除此之外

  • prototype属性
  • \[scope]属性 指向调用当前函数的所在地上下文
  • 有一个特殊属性保存了函数体内容
  • ...
    TDZ

暂时性死区,let const class声明的变量之后才能访问值和赋值

这一步对于let const class声明的变量不进行赋值,js中对于未赋值的变量进行访问会报错(所谓TDZ)

至此,全局执行上下文生成完毕,开始执行代码

函数执行上下文

执行上下文栈

下面这段代码执行的结果是什么?

javascript 复制代码
// 执行前 (全局执行上下文)window.b = 函数对象   window.a = 函数对象
// 执行

function b() {
  console.log('hello');
}

function a() {
  b()

  function b() {
    console.log(c)
  }
  function c() {
    console.log(b);
  }
}
a();

我们从原理的角度刨析这段代码!

b和a都是全剧终生命的变量。执行a时,要生成a的执行上下文,称作函数执行上下文。

在JS中用栈结构管理执行上下文,称作执行上下文栈ECS

当函数执行的前一刻,生成该函数的执行上下文,并压入栈顶,函数执行结束,则他的执行上下文出栈

函数的执行上下文与全局执行上下文生成流程差不多,区别是

  • 函数执行上下文中没有全局对象,Lexical Environment由scope(var let const class创建的变量统统在这 ) 和 outter组成
  • 函数的this Binding默认是全局对象,严格模式下是undefined,可以通过不同的调用方式更改thi Binding的值

这里我们着重说一下outter

全面执行上下文的outter是什么?还记得吗,是null

函数执行上下文有所区别,它的值是,函数对象的\[scope]属性,这个outter的作用是什么呢?

那就不得不说一下函数中查找变量的机制了: 在执行上下文中找不到变量时,则会查找outter指向的执行上下文,这其实就是所谓的 作用域链的底层机制

相关推荐
github_is_geeksKai1 小时前
浏览器端文件处理的边界:PDF 面单、GPX 隐私与 EPUB 修复
前端
李纲明1 小时前
微信小程序 getSystemInfo 提示已废弃、屏幕高度算错胶囊还对不齐?getWindowInfo 和 getDeviceInfo 怎么接才稳
javascript·微信小程序·小程序·小程序开发·devdiy
deli0072 小时前
从一句反馈到一次升级:Mystudy 的自进化实践
前端
FungLeo2 小时前
成为全栈·Vue 管理后台篇·用 fetch 建一层可控的请求内核
前端·javascript·vue.js·http·fetch·formdata·接口封装
用户84298142418102 小时前
ByteJS,让重要的 JavaScript 以字节码运行。
javascript
FungLeo4 小时前
成为全栈·Vue 管理后台篇·Vue Router如何守住多角色后台边界
前端·javascript·vue.js·rbac·vue router·路由守卫·前端权限
FungLeo4 小时前
成为全栈·Vue 管理后台篇·分页只显示第一页:从接口total 定位到前端修复
前端·vue.js·状态模式·分页·naive ui·服务端分页·前端问题排查
ZhengEnCi4 小时前
苹果滑动为什么有「肉感」:橡皮筋越界阻尼与弹簧动画的物理原理
前端
Moment5 小时前
不会后期的我,发现了一个开源胶片神器😍😍😍
前端·后端·开源
L1mbo5 小时前
Lite模式 缓解微信开发者工具卡顿,附 uni-app 实践方案
前端·微信小程序