前言
对于一名前端开发者来说,深入理解JavaScript程序内部执行机制当然是很有必要的,其中一个关键概念就是JavaScript的执行上下文和执行栈,理解这部分内容也有助于理解作用域、闭包等
本次重点
- 执行上下文概念、类型、特点
- 执行上下文的生命周期
- 关于变量提升
- this指向问题
- 执行上下文栈
基本概念:
所谓的JavaScript执行上下文就是当前JS代码代码被解析和执行时所在环境的抽象概念,js代码都是在执行上下文中运行的
一、执行上下文类型
1.全局执行上下文
它的特点有以下几个:
a.它是最基础、默认的全局执行上下文
b.它会创建一个全局对象,并且将this指向全局对象,在浏览器中全局对象是window,在nodejs中全局对象是global
c.一个程序中只有一个
2.函数执行上下文
它的特点有以下几个:
a.有自己的执行上下文
b.可以在一个程序中存在任意数量
c.是函数被执行时创建
3.eval函数执行上下文:
eval函数可以计算某个字符串,并执行其中的js代码,这样就会存在一个安全性问题,在代码字符串未知或者是来自于用户输入源的话,绝对不要使用eval函数
以上就是执行上下文的几种类型和相应的特点,我们可以看下下面这段代码:
里面的三个函数都被执行了,所以是有三个函数执行上下文
// 全局执行上下文
var sayHello = 'Hello'
function someone() {
// 函数执行上下文
var first = 'Tom', last = 'Ada'
function getFirstName() {
// 函数执行上下文
return first
}
function getLastName() {
// 函数执行上下文
return last
}
console.log(sayHello + getFirstName() + getLastName())
}
someone()
二、执行上下文的生命周期
执行上下文的生命周期分了三个阶段:
- 创建阶段
- 执行阶段
- 回收阶段
创建阶段
对于函数执行上下文,函数被调用的时候,但是还未执行里面的代码之前,会做三件事情:
- 创建变量对象:会初始化函数的参数,提升函数声明和变量声明
- 创建作用域链:作用域链用于标识符解析,看下面代码:
f3函数被调用的时候,里面的变量num要求被解析的时候,会在当前f3的作用域里查找,如果没找到,就会向上一层作用域中查找,直到在全局作用找到该变量为30
var num = 30;
function f1() {
function f2() {
function f3() {
console.log(num);
}
f3();
}
f2();
}
f1();
- 确定this指向:这个情况比较多,会在下文统一介绍
在一个程序执行之前,要先解析代码,会先创建全局执行上下文环境,把需要执行的变量和函数声明都取出来并暂时赋值为undefined,函数也要先声明好待调用,这也是我们下文中会讲到的变量提升,以上几步做完后