js执行上下文

2020-04-16  本文已影响0人  简单tao的简单

JS代码的执行顺序有时与代码先后顺序有所差异,抛开异步代码,即使是同步代码,它的执行也与你的预期不一致,比如:

console.log(f1) // f1() {console.log('echo');}

function f1() {
    console.log('听风是风');
};
f1(); //echo

function f1() {
    console.log('echo');
};
f1(); //echo

按照代码书写顺序,应该先输出 听风是风,再输出 echo才对,很遗憾,两次输出均为 echo;如果我们将上述代码中的函数声明改为函数表达式,结果又不太一样:

console.log(f1) // undefined

var f1 = function () {
    console.log('听风是风');
};
f1(); //听风是风

var f1 = function() {
    console.log('echo');
};
f1(); //echo

这说明代码在执行前一定发生了某些微妙的变化,JS引擎究竟做了什么呢?这就不得不提JS执行上下文了。

JS执行上下文

JS代码在执行前,JS引擎会做一番准备工作,这份工作其实就是创建对应的执行上下文,js执行上下文有一套规则,规范变量存储、提升、this指向

function wrap(){
    console.log("函数执行上下文环境")
}
wrap();
wrap();
wrap();
wrap();
wrap();
console.log("全局执行上下文环境")
//6个执行上下文环境

全局执行上下文

全局执行上下文只有一个,在客户端中一般由浏览器创建,也就是我们熟知的window对象,我们能通过this直接访问到它。

console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}

全局对象window上预定义了大量的方法和属性,我们在全局环境的任意处都能直接访问这些属性方法,同时window对象还是var声明的全局变量的载体。我们通过var创建的全局对象,都可以通过window直接访问。

var a = 1;
var b = 2;
console.log(window)

函数执行上下文

函数执行上下文可存在无数个,每当一个函数被调用时都会创建一个函数上下文;需要注意的是,同一个函数被多次调用,都会创建一个新的上下文。
说到这你是否会想,上下文种类不同,而且创建的数量还这么多,它们之间的关系是怎么样的,又是谁来管理这些上下文呢,这就不得不说说执行上下文栈了

规则

全局执行上下文
1.var定义的全局变量==>undefined, 添加为window的属性
2.function声明的全局函数==>赋值(fun), 添加为window的方法
3.提升
4.this==>赋值(window)

函数执行上下文
1.形参变量==>赋值(实参)
2.arguments==>赋值(实参列表)
3.处理 var定义的局部变量
4.处理 function声明的函数
5.提升
6.this==>赋值(调用函数的对象)

提升

执行上下文栈

执行上下文栈(下文简称执行栈)也叫调用栈,执行栈用于存储代码执行期间创建的所有上下文,具有LIFO(Last In First Out后进先出,也就是先进后出)的特性。
JS代码首次运行,都会先创建一个全局执行上下文并压入到执行栈中,之后每当有函数被调用,都会创建一个新的函数执行上下文并压入栈内;由于执行栈LIFO的特性,所以可以理解为,JS代码执行完毕前在执行栈底部永远有个全局执行上下文。

理解压栈

作用域和执行上下文的关系

作用域和执行上下文的区别

上一篇 下一篇

猜你喜欢

热点阅读