我觉得这个问题的真正答案通常被“提升机”这个词抽象出来。这是真正发生的事情。
每次在 JavaScript 中运行函数时,都会为该函数创建一个新的执行上下文,并将其推送到执行堆栈中。所以在你的第二个例子中,你有以下代码:
var me = 1;
function findme(){
if(me){
var me = 100;
console.log(me);
}
console.log(me);
}
findme();
// undefined
在这段代码执行的最开始(假设这是整个 JavaScript),首先发生的是 JavaScript 引擎创建一个全局执行上下文。在创建过程中,它为该上下文中的所有函数和变量分配内存。函数按照您想象的方式分配和初始化,但变量只是首先分配(未正确初始化)。
因此,在此示例中创建全局执行上下文之后,函数 findme() 将被完整地分配到内存中,但变量“me”将被分配一个未定义的初始值。在创建全局执行上下文之后,然后运行代码。它发现 var me = 1; 并将“me”变量从 undefined 更新为 1。它实际上并没有对函数定义做任何事情,但是,它找到了“findme();”的函数调用。
此时,我们进入 findme() 函数。真的,同样的事情再次发生。为这个函数创建一个执行上下文,它被推到全局执行堆栈上,这成为运行代码。如果你理解我讨论的第一部分,我想你会意识到“console.log(me);” 在“if”语句未定义之后调用。为什么?因为在创建 findme() 函数执行上下文时,它最初创建了“me”变量,因为它在其上下文中看到了“var me = 100;” 陈述。但是,就全局执行堆栈而言,“if”语句不会获得专用的执行上下文。因此,当“console.log(me);” 在 if 之外运行 me 变量 IS 在函数的总体上下文中定义。
如果您遵循了所有这些,您现在了解了 JavaScript 引擎如何工作的主要部分。