浅谈js执行原理

预计阅读时间: 4 分钟

js的执行原理(ES3)

1. 基础概念

"基础概念

堆内存(stack),JS引擎对于复杂数据类型内存的分配,会在堆内存中 开辟一块空间,并且将这块空间的指针返回值 给变量引用;

栈内存(Heap),JS引擎对于原始数据类型内存的分配,会在执行时, 直接在栈空间进行分配

"执行上下文概念
  • GO(global object) 全局对象
  • VO(variable object) 变量对象
  • AO(activation object) 活动对象
  • ECS(excution Contexts) 执行上下文
多个活跃的执行上下文会形成一个逻辑上的栈结构,成为执行栈,顶部是正在执行的执行上下文

2. 执行过程

2.1 执行流程

第 1 步 初始化GO

js引擎在执任何代码之前, 会初始化一个全局对象 GO

  • 该对象所有的作用域都可以访问
  • 包含一些默认的内置对象,Date、Array等
  • 会根据当前环境注入一些全局对象,如浏览器是window

第 2 步 代码解析过程

代码解析过程,会把全局声明的变量,放到GO中,作为它的一个属性,此时值为undefined,如果遇到全局的函数声明,会立即创建函数对象====函数可以先调用,后声明 。这里就是变量作用域提升

第3步 代码执行过程

  • 执行栈的VO就是GO,赋值语句会把值赋予给Go中声明的属性
  • 如果遇到函数调用,则会立即创建一个新的执行栈

第4步 函数执行过程

  • 函数执行时,会首先创建一个AO,作为执行栈的VO,AO是以函数的arguments作为初始值创建
  • 如果函数中有变量声明,则会加到AO中作为一个属性,函数声明也会被立即创建函数 ====(注意VO并不等同于函数本身) 这里就是变量作用域提升
  • 函数声明的时候作用域链就已经确定,和调用的位置无关,亦即创建函数的时候已经确定了scope

2.2 执行上下文示意图

1var message = "hello world"
2function foo(num){
3  console.log(message) //undeifined
4  console.log(num) //123
5  var message ="hello you"
6  var num =23456
7  num= 90
8  }
9 foo(123)  
10 
11 var name= "anron"

2.3 官方描述

  1. 每一个执行上下文会关联一个VO(Variable Object,变量对象),变量和函数声明会被添加到这个VO对象中
  • 当进入一个函数执行上下文时,会创建一个AO对象(Activation Object);
  • 这个AO对象会使用arguments作为初始化,并且初始值是传入的参数;
  • 如果函数有默认参数,则会在初始化后检测每个参数是否已被赋值,如无(为undefined),则使用默认参数赋值。 亦即给默认参数 传入的值是undefined的话,也是使用默认参数的值
  • 这个AO对象会作为执行上下文的VO来存放变量的初始化;
  1. 进入到一个执行上下文时,执行上下文也会关联一个作用域链(Scope Chain)
  • 作用域链是一个对象列表,用于变量标识符的求值;
  • 当进入一个执行上下文时,这个作用域链被创建,并且根据代码类型,添加一系列的对象;

浏览器 会对作用域链优化

2.6 面试题

函数中return后面的代码真的可以安全删除吗?

1// 面试题1
2var n = 100
3function foo(){
4   console.log(n) // undefined  创建AO时,函数还没有执行,所以内部的n已经在AO里了
5   return
6   var n = 10
7}
8
9//面试题2
10foo(){
11  var a=b=100 // 这里只声明了a,而b会被当成一个全局变量
12}
13foo()
14console.log(a) // error
15console.log(b) // 100 
16
17b = 10 //在外层作用域,不声明变量,直接赋值,会被挂在全局作用域上

3. ES6中的变化

"ES6中的变化

一些名称会有改变,使用const let关键词,消除了作用域提升

词法环境: 是一种规范类型,用于在词法嵌套结构中定义关联的变量、函数等标识符

  • 一个词法环境由环境记录 (Environment Record)和外部词法环境(Outer Lexical Environment)组成
  • 一个词法环境经常用于关联一个函数声明、代码块语句、try...catch语句,当它们的代码被执行时,词法环境被创建出来

全局的Environment Record是一个合成的对象,包含

Declarative Environment Global Environment