简体   繁体   English

了解javascript提升和执行上下文

[英]Understanding javascript hoisting and execution context

b();
console.log(a);

var a = 'Hello World';

function b(){
    console.log('Called b!');
}

I have read about the term "hoisting", but it isn't pretty clear to me. 我已经读过“起重”一词,但对我来说还不太清楚。 Why does the function gets executed while the variable is set to undefined? 为什么在变量设置为undefined的情况下执行函数?

The interesting part is, the variable didn't show any error. 有趣的是,变量没有显示任何错误。 But it showed undefined. 但它显示未定义。 But when I remove the variable totally, then it shows an error. 但是,当我完全删除该变量时,它将显示一个错误。 That means, the variable is present somewhere though. 这意味着,变量存在于某个地方。 right? 对?

But if it is present, then why can't the compiler compile it and can compile the function here? 但是,如果存在,那么为什么编译器不能编译它并且可以在此处编译函数?

I know that var a is getting hoisted. 我知道var a正在挂起。 I want to know why the engine is treating the variable and the function in a different way that is what's happening behind the scenes during the execution context. 我想知道为什么引擎以不同的方式来处理变量和函数,这就是执行上下文在幕后发生的事情。

Any detailed explanation would be helpful about how the engine is creating the execution context. 任何详细的解释都将有助于引擎如何创建执行上下文。

In this question I'm asking about how javascript engine is behaving differently with the function and the variable. 在这个问题中,我想问一问javascript引擎在函数和变量上的表现如何不同。 And what is exactly happening in the creating state and execution state of the execution phase. 在执行阶段的创建状态和执行状态中到底发生了什么。 So, it's not a duplicate question. 因此,这不是一个重复的问题。

But if it is present, then why can't the compiler compile it and can compile the function here? 但是,如果存在,那么为什么编译器不能编译它并且可以在此处编译函数?

Basically it boils down to whether the value of the binding can be determined without executing the code or not. 基本上,归结为是否可以在不执行代码的情况下确定绑定的值。

The function declaration itself doesn't depend on runtime information. 函数声明本身不依赖于运行时信息。 Keep in mind that the body is not evaluated until the function is called. 请记住,在调用函数之前不会对主体进行评估。 So even without really executing the code, its clear that the value of b is a function. 因此,即使没有真正执行代码,也很清楚b的值是一个函数。

However, the initialization value of a variable declaration may depend on runtime information. 但是,变量声明的初始化值可能取决于运行时信息。 Consider this: 考虑一下:

var a = 10 + bar();

There is no way for the engine to "hoist" the initialization value without evaluating the expression (and executing bar in the process). 如果不评估表达式(并在过程中执行bar ),则引擎无法“提升”初始化值。

Of course in your example, the initialization value ( 'Hello World' ) is static as well, so it could be hoisted. 当然,在您的示例中,初始化值( 'Hello World' )也是静态的,因此可以将其提升。 But then the behavior would be inconsistent and probably more confusing. 但是这样的行为将是不一致的,并且可能更加令人困惑。


What exactly happens when control enters a new function is defined in the spec . 规范中定义了当控制进入一个新功能时会发生什么情况。 There you can see how variable declarations and function declarations are treated. 在那里您可以看到如何处理变量声明和函数声明。

With hoisting, this is what your code looks like 使用提升,这就是您的代码的样子

function b(){
    console.log('Called b!');
}
var a;

b();
console.log(a);

a = 'Hello World';

As you can see, a is declared at the the top, but has not been set to a value yet. 如您所见, a在顶部声明,但尚未设置为值。 That is why you get undefined when you log that variable. 这就是为什么在记录该变量时undefined原因。

If you remove the a variable altogether, you get the Uncaught ReferenceError because a has not been declared. 如果删除了a完全可变的,你得到的Uncaught ReferenceError因为a尚未声明。

The above code is same as below 上面的代码与下面的相同

var a;
function b(){
    console.log('Called b!');
}
b();
console.log(a);

a = 'Hello World';

Explanation - Function along with its definition are hoisted to the top. 说明-函数及其定义被提升到顶部。 Variable declaration is hoisted not its definition 悬挂变量声明而不是定义

var a; is hoisted. 被悬挂。 a = 'Hello World!'; is not hoisted. 没有悬挂。 It's that simple. 就这么简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM