JavaScript变量未定义vs未定义

时间:2022-01-10 08:07:15

I have an HTML page with the following JavaScript attached.

我有一个HTML页面,附带如下JavaScript。

alert(box);
box = "Thinking outside the box";

In the console I get "Uncaught ReferenceError: box is not defined"

在控制台中,我得到“Uncaught ReferenceError: box未定义”

when I change it to:

当我把它改为:

alert(box);
var box = "Thinking outside the box";

The alert gets called and shows undefined. I need to be able to explain this, I have a vague idea of why this happens. I know that when I use var, JavaScript knows the variable is there before the alert is executed, but has not necessarily assigned a value to it?? Am I way off here? Need some help understanding this.

警报被调用并显示未定义。我需要能够解释这个,我对为什么会发生这种情况有一个模糊的概念。我知道,当我使用var时,JavaScript知道在执行警报之前变量就在那里,但它没有分配值吗?我离这儿很远吗?需要一些帮助来理解这一点。

2 个解决方案

#1


9  

When you define a variable with var, the declaration of the variable is "hoisted" to the top of the scope and thus the variable is defined for the entire scope. The initialization of the variable (assigning it's initial value) remains at the same location in the code.

当您使用var定义一个变量时,该变量的声明被“提升”到范围的顶部,因此该变量被定义为整个范围。变量的初始化(分配它的初始值)保持在代码中的相同位置。

So, in your second example, when you do alert(box), the variable box has already been declared because of the hoisted var statement. Your second example:

因此,在第二个示例中,当您执行alert(box)时,变量框已经被声明,因为包含了提升的var语句。你的第二个例子:

alert(box);
var box = "Thinking outside the box";

is basically equivalent to this (the declaration of the box variable is hoisted to the top of the scope):

与此基本等价(将箱体变量的声明提升到范围的顶部):

var box;
alert(box);
box = "Thinking outside the box";

This makes the box variable declared (though not initialized) before your alert(box) statement and thus you get a result that is consistent with the variable being declared, but having no value yet (the alert() reports undefined which is what happens when the variable exists, but is not yet initialized).

这使box变量在alert(box)语句之前声明(虽然没有初始化),因此您得到的结果与所声明的变量一致,但是还没有值(alert()报告未定义,这是变量存在时发生的情况,但还没有初始化)。

Your first example does not use var and thus there is no hoisting so at the point where you do alert(box), there is no variable at all named box and thus you get the uncaught reference error.

第一个示例不使用var,因此没有提升,所以在使用alert(box)时,根本没有命名为box的变量,因此会得到未捕获的引用错误。

There are many, many posts here on SO that describe the details of hoisting. You can see a long list of them here: https://*.com/search?q=javascript+variable+hoisting where you will find further explanation of variable hoisting.

这里有很多很多的贴子来描述提升的细节。您可以在这里看到一个长长的列表:https://*.com/search?q=javascript+变量+提升,你可以在这里找到关于变量提升的进一步解释。

Note: function declarations are also hoisted so some of the posts you find will be about function declarations rather than variable declarations, though the concept is pretty much the same.

注意:函数声明也被提升,因此您发现的一些文章将是关于函数声明而不是变量声明的,尽管概念基本相同。

#2


2  

This has to do with variable hoisting. What this means is that, variable declarations (and declarations in general) are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it is declared.

这与变量提升有关。这意味着,在执行任何代码之前,都要处理变量声明(和一般的声明),在代码中的任何地方声明一个变量就等于在顶部声明它。这也意味着变量可以在声明之前使用。

When you do the following:

当你这样做时:

alert(box)
var box = "Thinking outside the box"

This is implicitly understood as:

这被含蓄地理解为:

var box;
alert(box);
box = "Thinking outside the box"

In your first case, you have no variable declarations, and hence is not hoisted, at at that point box is undefined

在第一种情况下,您没有变量声明,因此没有挂起,在那个点框中没有定义

Why does this happen?

这为什么会发生?

As Stoyan Stefanov explains in his book "JavaScript Patterns", hoisting is a result of the implementation of the JavaScript interpreter:

正如Stoyan Stefanov在他的书“JavaScript模式”中解释的,提升是JavaScript解释器实现的结果:

For completeness, let’s mention that actually at the implementation level things are a little more complex. There are two stages of the code handling, where variables, function declarations, and formal parameters are created at the first stage, which is the stage of parsing and entering the context. In the second stage, the stage of runtime code execution, function expressions and unqualified identifiers (undeclared variables) are created. But for practical purposes, we can adopt the concept of hoisting, which is actually not defined by ECMAScript standard but is commonly used to describe the behaviour.

为了完整性,让我们提一下,实际上在实现级别,事情要复杂一些。代码处理有两个阶段:变量、函数声明和正式参数在第一个阶段创建,这是解析和进入上下文的阶段。在第二阶段,创建运行时代码执行阶段、函数表达式和非限定标识符(未声明变量)。但在实际应用中,我们可以采用提升的概念,它实际上不是由ECMAScript标准定义的,而是通常用于描述行为。

- Stoyan Stefanov, "JavaScript Patterns"

- Stoyan Stefanov,“JavaScript模式”

As a side read, linking this article from Safe Shepherd.

一边阅读,把这篇文章与安全的牧羊人联系起来。

#1


9  

When you define a variable with var, the declaration of the variable is "hoisted" to the top of the scope and thus the variable is defined for the entire scope. The initialization of the variable (assigning it's initial value) remains at the same location in the code.

当您使用var定义一个变量时,该变量的声明被“提升”到范围的顶部,因此该变量被定义为整个范围。变量的初始化(分配它的初始值)保持在代码中的相同位置。

So, in your second example, when you do alert(box), the variable box has already been declared because of the hoisted var statement. Your second example:

因此,在第二个示例中,当您执行alert(box)时,变量框已经被声明,因为包含了提升的var语句。你的第二个例子:

alert(box);
var box = "Thinking outside the box";

is basically equivalent to this (the declaration of the box variable is hoisted to the top of the scope):

与此基本等价(将箱体变量的声明提升到范围的顶部):

var box;
alert(box);
box = "Thinking outside the box";

This makes the box variable declared (though not initialized) before your alert(box) statement and thus you get a result that is consistent with the variable being declared, but having no value yet (the alert() reports undefined which is what happens when the variable exists, but is not yet initialized).

这使box变量在alert(box)语句之前声明(虽然没有初始化),因此您得到的结果与所声明的变量一致,但是还没有值(alert()报告未定义,这是变量存在时发生的情况,但还没有初始化)。

Your first example does not use var and thus there is no hoisting so at the point where you do alert(box), there is no variable at all named box and thus you get the uncaught reference error.

第一个示例不使用var,因此没有提升,所以在使用alert(box)时,根本没有命名为box的变量,因此会得到未捕获的引用错误。

There are many, many posts here on SO that describe the details of hoisting. You can see a long list of them here: https://*.com/search?q=javascript+variable+hoisting where you will find further explanation of variable hoisting.

这里有很多很多的贴子来描述提升的细节。您可以在这里看到一个长长的列表:https://*.com/search?q=javascript+变量+提升,你可以在这里找到关于变量提升的进一步解释。

Note: function declarations are also hoisted so some of the posts you find will be about function declarations rather than variable declarations, though the concept is pretty much the same.

注意:函数声明也被提升,因此您发现的一些文章将是关于函数声明而不是变量声明的,尽管概念基本相同。

#2


2  

This has to do with variable hoisting. What this means is that, variable declarations (and declarations in general) are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it is declared.

这与变量提升有关。这意味着,在执行任何代码之前,都要处理变量声明(和一般的声明),在代码中的任何地方声明一个变量就等于在顶部声明它。这也意味着变量可以在声明之前使用。

When you do the following:

当你这样做时:

alert(box)
var box = "Thinking outside the box"

This is implicitly understood as:

这被含蓄地理解为:

var box;
alert(box);
box = "Thinking outside the box"

In your first case, you have no variable declarations, and hence is not hoisted, at at that point box is undefined

在第一种情况下,您没有变量声明,因此没有挂起,在那个点框中没有定义

Why does this happen?

这为什么会发生?

As Stoyan Stefanov explains in his book "JavaScript Patterns", hoisting is a result of the implementation of the JavaScript interpreter:

正如Stoyan Stefanov在他的书“JavaScript模式”中解释的,提升是JavaScript解释器实现的结果:

For completeness, let’s mention that actually at the implementation level things are a little more complex. There are two stages of the code handling, where variables, function declarations, and formal parameters are created at the first stage, which is the stage of parsing and entering the context. In the second stage, the stage of runtime code execution, function expressions and unqualified identifiers (undeclared variables) are created. But for practical purposes, we can adopt the concept of hoisting, which is actually not defined by ECMAScript standard but is commonly used to describe the behaviour.

为了完整性,让我们提一下,实际上在实现级别,事情要复杂一些。代码处理有两个阶段:变量、函数声明和正式参数在第一个阶段创建,这是解析和进入上下文的阶段。在第二阶段,创建运行时代码执行阶段、函数表达式和非限定标识符(未声明变量)。但在实际应用中,我们可以采用提升的概念,它实际上不是由ECMAScript标准定义的,而是通常用于描述行为。

- Stoyan Stefanov, "JavaScript Patterns"

- Stoyan Stefanov,“JavaScript模式”

As a side read, linking this article from Safe Shepherd.

一边阅读,把这篇文章与安全的牧羊人联系起来。