我觉得这个问题的真正答案经常被“提升机”这个词抽象掉。这是真正发生的事情。
每次在 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 变量。
如果您遵循了所有这些,您现在就了解了 JavaScript 引擎如何工作的主要部分。