关于js的执行时的梳理
在js的执行期间,包含了许多我们看不到的步骤,这些步骤可以更好的让我们去知晓我们定义的变量的可访问情况,以下是一些相关的知识梳理
预编译阶段 💻
预编译阶段会将一些函数变量声明进行提升,以下是es5中的两种函数申明方式的区别
var
js在预编译阶段,以var形式声明的变量会在内存空间中为变量开辟一个新的内存空间,指向这个变量名,同时将新创建的变量赋值为undefined,执行阶段才会赋值
function
用函数申明的形式创建的函数会在内存中开辟内存空间,并对函数执行创建的工作,在这个阶段作用域已经定义
引擎运行执行阶段
一、执行上下文创建阶段 在函数的创建阶段中,经历以下几步操作
-
1 生成变量对象
-
2 建立作用域链
-
3 确定this指向
1 生成变量对象
在执行上下文的创建阶段,变量对象会储存着
函数所有的形参 ----赋值为undefined
所有的函数声明 ---在内存空间中开辟空间
所有的变量声明 ---赋值为undefined---如果与函数或者形参名相同,也不会干扰到
2 建立作用域链
在此时作用域链将被创建,函数在当前作用域下RHS引用没有访问到变量的话,可以通过作用域链逐级向上访问变量
3 确立this的指向
在这一阶段,this的指向会得到确立
this的指向时在调用时期确立的,而不是在函数定义时期确立的
总结:
this
主要与调用该函数的对象相关联,影响到了该对象中的数据是否可以通过this访问,主要关联的是调用该函数的对象数据
作用域
主要与函数的定义相关联,影响到了函数中定义的变量的可见性,也就是说主要关联着我们函数定义的变量数据
二、执行上下文的执行阶段
-
1 对之前创建的变量进行赋值
-
2 对函数进行引用
-
3 执行其他的代码
在这个时期,之前创建阶段所定义的形参函数声明等都会得到赋值,同时内部定义的代码也会得到执行 在此时,变量对象也会转换为书上所说的活动对象
拓展知识:
关于作用域与作用域链建立时期的区分:
在创建阶段下定义的函数作用域已经确立
作用域链是在函数执行的期,执行上下文创建阶段确立的
可变对象: 所有压入函数作用域链的值,都是对可变对象的引用,当所有对这个可变对象的引用都断开的时候, 这个可变对象才能被垃圾回收
关于作用域创建阶段和运行时阶段
一、创建时阶段
当浏览器窗口打开的时候,就会自动开启一个最顶级的运行时阶段的作用域 一般称之为全局作用域,在这个作用域中定义出来的函数会自动进入创建时阶段,拥有自己的作用域 创建时阶段会创建自己运行时阶段的可变对象引用,逐级插入作用域链中,直到最后一个顶级的global对象
二、运行时阶段
运行时阶段是指函数通过()运行的时候,会创建一个运行期上下文对象,拥有自己的[[scope]]属性,然后推入作用域链中