JavaScript之执行上下文

173 阅读3分钟

执行上下文是指javascript代码在运行时的环境。

JavaScript 引擎并非一行一行地分析和执行程序,而是一段一段地分析执行,创建了执行上下文栈来管理执行上下文。

两种类型

  • 全局执行上下文:默认的,创建一个全局window对象,设置this指向全局对象。

  • 函数执行上下文:每当一个函数被调用时,都会为该函数创建一个新的上下文。

执行栈

用来存储代码运行时创建的所有执行上下文,遵循LIFO(后进先出)的数据结构。

它会先创建一个全局执行上下文压入执行栈,当遇到函数调用,该函数会创建一个新的执行上下文压入栈的顶部。

先执行位于栈顶的函数,该函数执行结束后,执行上下文会从栈中弹出。

创建阶段

1. this值的绑定

全局上下文中,this指向全局对象,函数执行上下文中,如果被引用对象调用,this指向被引用的对象

2.创建词法环境的组件

词法环境是一种持有标识符到变量映射的结构,标识符指变量或函数的名字,变量是指实际对象或原始数据的引用。

词法环境内部有两个组件:

  • 环境记录器是存储变量和函数声明的实际位置
  • 外部环境的引用是它可以访问父级的词法环境。

词法环境的两种类型:

  • 全局环境没有外部环境的引用,拥有内建的Object/Array等在环境记录器内的原型函数,还有自定义的全局对象,this指向全局对象。
  • 函数环境中,函数内部定义的变量存储在环境记录器中,引用的外部环境可能是全局环境,或者包含此内部函数的外部函数。

环境记录器的两种类型:

  • 声明式环境记录器存储变量,函数,参数
  • 对象环境记录器定义出现在全局上下文中的变量和函数的关系

总之,

全局环境中,环境记录器是对象环境记录器。 函数环境中,环境记录器是声明式环境记录器,它还包含了一个传递给函数的arguments对象(存储索引和参数的映射的伪数组类型)和传递给函数的参数的length

3.创建变量环境的组件

同样是一个词法环境,它的环境记录器有变量声明语句在执行上下文中的创建的绑定关系。

词法环境和变量环境的不同就是:

  • 词法环境用来存储函数声明和变量:let和const绑定
  • 变量环境用来存储var变量绑定

声明提升

变量声明提升是指先调用变量,后声明变量,而不会抛出异常的js机制

在代码运行开始之前,执行上下文创建阶段,var声明会提升至当前作用域的顶部(只是声明,不涉及赋值,变量赋值留在原位置),letconst声明不提升。

console.log(i);// 声明提升,输出undfined
var i = 1;

等价于

var i;
console.log(i); // undefined
i = 1; // 初始化不提升

函数声明提升是指先调用函数,再声明并定义该函数,不会抛出异常

f(); //输出 test
function f() {
  console.log("test")
}

等价于

function f() {
  console.log("test")
};
f(); //输出 test

变量或函数同名

function xx(){ }

这种是函数声明,即声明一个函数,执行前会被提升,做初始化。

var xx= function(){ }

这种是变量赋值,匿名函数作为变量赋值给定义的变量,不会做初始化 ,初始化过程会在执行过程中进行.

console.log(typeof foo); // function pointer
console.log(typeof bar); // undefined
var foo = 'hello';
var bar = function() {
    return 'world';
};
function foo() {
    return 'hello';
}

提升之后等价于

var foo;
var bar;
function foo() {
    return 'hello';
}
console.log(typeof foo); // function pointer
console.log(typeof bar); // undefined
foo = 'hello';
bar = function() {
    return 'world';
};

一道面试题:www.cnblogs.com/xxcanghai/p…