javascript 声明与初始化变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31714434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 14:14:34  来源:igfitidea点击:

Declaring vs Initializing a variable?

javascriptvariable-declarationvariable-initialization

提问by user3247128

I'm curious to know the difference between declaring a variable, and initializing a variable. e.g.

我很想知道声明变量和初始化变量之间的区别。例如

var example; // this is declaring

var example = "hi" // initializing? Or just "adding a value"?

I don't think I'm right there, but what exactly is the definition of each? Or do they basically mean the same thing?

我不认为我就在那里,但是每个人的定义究竟是什么?或者它们基本上是同一个意思?

回答by jmar777

Edit: @ThisClark said something in the comments, and I went to prove him wrong, and upon reading the spec some more I learned something:

编辑:@ThisClark 在评论中说了些什么,我去证明他错了,在阅读规范后,我学到了一些东西:

Here's an informative except from the specification:

这是规范之外的信息:

A varstatement declares variables that are scoped to the running execution context's VariableEnvironment. Var variables are created when their containing Lexical Environment is instantiated and are initialized to undefinedwhen created. [...] A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer's AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.

一个var声明宣称,被限定在运行中的执行上下文的VariableEnvironment变量。Var 变量在其包含的词法环境被实例化undefined时创建,并在创建时初始化。[...] 由带有初始化程序的 VariableDeclaration 定义的变量在执行 VariableDeclaration 时被分配其初始化程序的 AssignmentExpression 值,而不是在创建变量时。

Based on my reading of this, the following points describe the behavior (and "correct-ish" usage of the terms) you asked about in your question:

根据我对此的阅读,以下几点描述了您在问题中询问的行为(以及术语的“正确”用法):

  • A variable declaration(e.g., var foo) causes that variable to be createdas soon as the "lexical environment" is instantiated. For example, if that variable were defined within a function body, that function is the "lexical environment", and so variable creation coincides with the instantiation of the function itself.

  • Obviously, variable declarationsmay or may not be created with an initializer(i.e., the right-hand expression that resolves to the variable's initial value). That's a pretty non-specification usage of the term "initial value", though... let's dig into that a bit more:

  • Technically, per the specification notes here, all variables are initialzed with the value undefined:

    variables are created [...] and are initialized to undefined

    Emphasis on "technically" there, as this is largely academic if an initializerwas also provided.

  • Based on what we've already covered, it should be understood that the statement var foo;could exist anywherewithin a function body, and moving it anywhere else within the same function would have no effect on the runtime semantics of the function itself (regardless of if/where any actual assignments or other references to footake place). If that's still confusing, re-read the previous points.

  • The last bit of behavior is the most intuitive part, and that's the assignmentof the initializer. This assignment takes place when that line of code is actually executed(which, again, isn't the same point in time when the variable technically got created).

  • 变量声明(例如,var foo)导致要该变量创建只要“词法环境”被实例化。例如,如果该变量是在函数体内定义的,则该函数就是“词法环境”,因此变量创建与函数本身的实例化相吻合。

  • 显然,变量声明可能会也可能不会使用初始化程序(即解析为变量初始值的右侧表达式)创建。这是术语“初始值”的一个非常非规范的用法,不过……让我们深入研究一下:

  • 从技术上讲,根据此处的规范说明,所有变量都使用以下值进行初始化undefined

    变量被创建 [...] 并被初始化为 undefined

    强调“技术上”,因为如果还提供了初始化程序,这在很大程度上是学术性的。

  • 根据我们已经介绍的内容,应该理解该语句var foo;可以存在于函数体内的任何位置,并且将它移动到同一函数内的任何其他位置不会对函数本身的运行时语义产生影响(无论 if/任何实际分配或其他参考foo发生的地方)。如果这仍然令人困惑,请重新阅读前面的要点。

  • 行为的最后一点是最直观的部分,这就是分配的的初始化。该赋值发生在该行代码实际执行时(同样,这与技术上创建变量的时间点不同)。

So, to quickly recap:

所以,快速回顾一下:

  • Allvariable declarations (that use var) are alwaysinitialized with undefinedupon the initialization of their lexical environment.
  • This initialization probably doesn't count as an assignment, in the technical sense (ha, @ThisClark, you werewrong!!). :)
  • Assignments are the easy part, as they behave the way (and at the point in time) that you expect.
  • 所有变量声明(使用var总是undefined在其词法环境初始化时初始化。
  • 这可能初始化不计为转让,在技术意义上(哈,@ThisClark,你错的!)。:)
  • 分配是容易的部分,因为它们的行为方式(以及在时间点)符合您的预期。

Hope that helps (and that I didn't terribly misinterpret the spec!).

希望这会有所帮助(并且我没有严重误解规范!)。

回答by Marcus Hughes

@jmar777's answer is definitely the best explanation and breakdown of the spec. However, I find that for us hands-on learners, a bit of illustrative code is helpful! ;)

@jmar777 的答案绝对是规范的最佳解释和细分。然而,我发现对于我们动手的学习者来说,一些说明性的代码是有帮助的!;)


The Basic Idea


基本理念

  • 'Declaration' makes a variable available throughout a given scope.
  • 'Assignment' gives a variable a specific value at that location in the code. If you attempt to assign a value to a variable that has never been declared in that scope or a parent scope, then the variable is implicitly declared on the global scope (equal to typing window.varName = value).
  • 'Initialization' is something that happens 'behind the scenes' or 'under the hood', so to speak. At runtime, all declaredvariables are initializedwith a beginning assignmentof undefined(even if they immediately get assigned a different value in the first line of code).
  • “声明”使变量在给定范围内可用。
  • “赋值”在代码中的那个位置给一个变量一个特定的值。如果您尝试为从未在该作用域或父作用域中声明的变量赋值,则该变量将在全局作用域中隐式声明(等同于 Typing window.varName = value)。
  • “初始化”是发生在“幕后”或“幕后”的事情,可以这么说。在运行时,所有的声明变量初始化一个开始分配undefined(即使他们立即会被分配在第一行代码不同的值)。

Thus, initialization isn't a term that matters to us. We declare and assign, and the Javascript engine initializes.

因此,初始化对我们来说不是一个重要的术语。我们声明并赋值,Javascript 引擎初始化。

So to directly answer the example in your question:

因此,要直接回答问题中的示例:

  • var example;declares a variable, which gets assigned a value of undefinedduring initialization.
  • var example = "hi"declares a variable, which also gets assigned a value of undefinedinitially, but when that line of code is actually reached during execution, it gets re-assigned to the string "hi".
  • var example;声明一个变量,该变量undefined在初始化期间被赋值为。
  • var example = "hi"声明一个变量,它undefined最初也被分配了一个值,但是当在执行过程中实际到达那行代码时,它被重新分配给字符串“hi”。


Illustrative Code


说明性代码

function testVariableDeclaration() {

    // This behaves 'as expected'....

    console.log(test2, 'no value assigned yet'); // --> undefined 'no value assigned yet'

    // ....but shouldn't our actual expectation instead be that it'll throw an error since
    // it doesn't exist yet? See the final console.log() below!


    // As we all know....

    test1 = 'global var'; // ....a variable assignment WITHOUT declaration in the current
                          // scope creates a global. (It's IMPLICITLY declared.)

    // But a little counter-intuitively....

    test2 = 'not global'; // Although this variable also appears to be assigned without
                          // declaration like 'test1', the declaration for 'test2' that
                          // appears *later* in the code gets hoisted so that it's already
                          // been declared in-scope prior to this assignment.

    console.log( test1, window.test1 === test1 ); // --> 'global var' TRUE
    console.log( test2, window.test2 === test2 ); // --> 'not global' FALSE

    var test2; // As shown by the above console.log() outputs, this variable is scoped.

    console.log( test3 ); // Throws a ReferenceError since 'test3' is not declared
                          // anywhere, as opposed to the first console.log() for 'test2'.
}


Effects of 'Scope' on Declaring/Assigning


“范围”对声明/分配的影响

What makes the difference between declaration and assignment even clearer is that declaringa variable always creates a new variable within the current scope (myVarscopeB), even if a variable of the same name already existed in a parent scope (myVarscopeA). Then we can assigna new value to myVarscopeBat any point in the current scope without re-declaring it. (This assignment does not affect the value of myVarscopeA.) Once the end of scopeBis reached, myVarscopeBwill no longer be available for assignment.

使声明和赋值之间的区别更加清晰的是,声明一个变量总是会在当前作用域 ( myVarscopeB)内创建一个新变量,即使父作用域 ( myVarscopeA) 中已经存在同名变量。然后我们可以在当前范围内的任何点为scopeB分配一个新值,而无需重新声明它。(该转让不影响价值scopeA)。一旦结束scopeB到达,scopeB将不再可用于分配。myVarmyVarmyVar

On the flip side, if we assign a value to a variable within a given scope withoutdeclaring it in that scope, it'll be assigned to the next-highest-up declaration in the 'scope chain' (or a global will be implicitly declared if no higher declaration is found).

另一方面,如果我们为给定范围内的变量赋值而不在该范围内声明它,它将被分配给“范围链”中的下一个最高声明(或者全局将被隐式如果没有找到更高的声明,则声明)。

Thus, a variable need only be declared once per scope, with each declaration overriding any declarations made in parent scopes (i.e. it creates a distinct variable). But it mustbe declared in-scope if it's meant to be unique to that scope. Assignment can happen as many times as desired, but only affects the most 'closely-declared' variable (for lack of a better term).

因此,一个变量只需要在每个作用域声明一次,每个声明覆盖在父作用域中所做的任何声明(即它创建一个不同的变量)。但是,如果它是该范围内唯一的,则必须在范围内声明它。赋值可以根据需要进行多次,但只影响最“密切声明”的变量(因为没有更好的术语)。

回答by bryc

The only difference is that the varstatement will initialize any declared variables without a value to undefined.

唯一的区别是该var语句将初始化任何没有值的声明变量 to undefined

In both examples, you are declaring a variable.

在这两个示例中,您都在声明一个变量。

If you assign a value to a variable without the varstatement, it will go down the scope chain looking for declared variables, eventually falling back to the global windowobject.

如果在没有var语句的情况下为变量赋值,它将沿着作用域链向下寻找已声明的变量,最终返回到全局window对象。

回答by Mohit Kanwar

There is a small thing that you are missing here. An analogy to understand the concept is like this. For each variable there has to be some value assigned to it.

您在这里缺少一件小事。理解这个概念的类比是这样的。对于每个变量,必须为其分配一些值。

The default value for all the variables (if not explicitly mentioned is undefined)

所有变量的默认值(如果没有明确提到是 undefined)

1) let example; // this is declaring and initializing with undefined

2) example="hi"; // this is assigning the value to hi

3) let example = "hi" // this is declaring and initializing with "hi"

so the 3rd statement is effectively the same as 1+2.

所以第三条语句实际上与 1+2 相同。

Now, a question may arise that when statement 3rd is possible, why do we need statement 1?

现在,可能会出现一个问题,当陈述 3 是可能的时,为什么我们需要陈述 1?

The reason is to expand the scope of variable.

原因是为了扩大变量的范围。

e.g. let us say that a variable is required at line number 8. But the value is not available until late and that too in a code block.

例如,假设第 8 行需要一个变量。但是该值直到很晚才可用,并且在代码块中也是如此。

1) {
2)  let a;
3)  try{
4)   a=someFunctionWhichMayThroeException();
5)  }
6)    catch(e){
7)         a=100;
8)  }
9)  someFunctionOnA(a);// the variable is required here
10)
11)  }

By declaring the variable above, we have increased the scope of the variable hence it can be used outside the try block.

通过声明上面的变量,我们增加了变量的范围,因此它可以在 try 块之外使用。

PS: this is just a trivial example of the usage.

PS:这只是一个简单的用法示例。

回答by deeeeeeekun

Declaration basically means introducing a new entity to the program. Initialization is giving a variable it's first value. So basically your above example is correct.

声明基本上意味着向程序引入一个新实体。初始化是给一个变量它的第一个值。所以基本上你上面的例子是正确的。

回答by Rizky Ariestiyansyah

Declaring is introduction of a new name in the program.

声明是在程序中引入一个新名称。

var test;        // Is this a declaration ?

Initialization refers to the "assignment" of a value.

初始化是指一个值的“赋值”。

var test = {first:"number_one"}  // Now that object is initialized with value

回答by ThisClark

Taken straight from the MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined:

直接取自 MDN: https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

The global undefined property represents the primitive value undefined. It is one of JavaScript's primitive types.

全局 undefined 属性表示未定义的原始值。它是 JavaScript 的原始类型之一。

Simply declaring a variable in Javascript, such as var exampleinitializes it to the primitive value of undefined. That means the following two expressions are equivalent:

简单的在Javascript中声明一个变量,比如var example初始化为undefined的原始值。这意味着以下两个表达式是等效的:

//equivalent expressions
var ex1;
var ex2 = undefined;

//true!
alert(ex2 === ex1);

What I don't know and can't test at this time is how far back in web browser history the alert will display true. For example, does this alert work in IE6 or some obscure Blackberry phone? I can't say for certain this is universal but it at least works in the latest versions of Firefox, Chrome, and Safari at the time of writing.

我目前不知道且无法测试的是,警报在 Web 浏览器历史记录中会显示多远。例如,此警报在 IE6 或一些不起眼的黑莓手机中是否有效?我不能肯定这是通用的,但在撰写本文时,它至少适用于最新版本的 Firefox、Chrome 和 Safari。