携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
可执行代码
JavaScript可执行代码有哪些呢?
三种,全局代码,函数代码,eval代码。
执行上下文
通俗点说,执行上下文就是,当去执行一个函数的时候就会进行准备动作,这个准备动作就叫做“执行上下文”。
JavaScript创建了执行上下文栈来管理执行上下文。
Execution context stack,ECS => 执行上下文栈
让我们举例子了解一下:
假设 执行上下文栈 是一个 数组:
ESC=[]
当JavaScript执行代码时首先遇到全局代码,即globalContext。所以初始化时首先向执行上下文栈压入全局执行上下文。并且,只有当整个应用程序运行结束时,ESC才会被清空,所以在程序结束之前,ESC最底部永远有全局执行上下文。
接下来执行下列代码:
function fun3() {
console.log('fun3')
}
function fun2() {
fun3();
}
function fun1() {
fun2();
}
fun1();
JavaScript引擎如何执行呢。
当执行一个函数时,就会创建一个函数执行上下文,并且压入执行上下文栈;当函数执行结束时,就会将此执行上下文从栈中弹出。
以上,是执行函数时的流程。(函数执行上下文:functionContext)
即,先在ESC栈中push压入fun1的执行上下文;
再push压入fun2的执行上下文;
再push压入fun3的执行上下文。
因为是栈中,栈中,所以遵循后进先出,即fun3最先执行完毕然后从栈中弹出。
ESC.pop();弹出fun3;
ESC.pop();弹出fun2;
ESC.pop();弹出fun1;
函数全部执行完毕,不要忘记ESC最底层有全局执行上下文glocalContext。
function foo() {
console.log('foo1');
}
foo();
function foo() {
console.log('foo2');
}
foo();
这段代码的输出结果是什么?
我们已经了解了执行函数的流程了,那么也照葫芦画瓢吧。
即,在ESC栈种push压入foo()的执行上下文;再压入foo()的执行上下文;
接着去执行foo()函数,发现有两个命名为foo的重复函数。(同级比较当然是取最后一个了,相同命名已经被覆盖了,最后一个才是有效滴)
那就输出结果foo2两个;
同时ESC.pop();弹出foo()
ESC.pop();弹出foo();
但是如果:::👇
var foo = function () {
console.log('foo1');
}
foo();
function foo() {
console.log('foo2');
}
foo();
与上一段代码相比只差了一个var声明,结果截然不同,众所周知函数声明的优先级要比变量声明更高,所以内部代码顺序为:
function foo() {
console.log('foo2');
}
var foo = function () {
console.log('foo1');
}
foo();
foo();
所以以上结果输出为两次foo1.