声明与初始化变量?

Declaring vs Initializing a variable?

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

var example; // this is declaring

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

我不认为我在那里,但每个的定义到底是什么?或者它们的意思基本相同?

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

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

除了 specification:

之外,还有其他信息

A var statement 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 undefined when 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.

根据我的阅读,以下几点描述了您在问题中询问的行为(以及 "correct-ish" 术语的用法):

  • 变量声明(例如,var foo)导致该变量尽快创建因为 "lexical environment" 被实例化了。例如,如果该变量是在函数体内定义的,则该函数就是 "lexical environment",因此变量创建与函数本身的实例化一致。

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

  • 技术上,根据此处的规范说明,所有变量都初始化为值 undefined:

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

    强调"technically",因为如果还提供了初始化器,这在很大程度上是学术性的。

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

  • 行为的最后一点是最直观的部分,那就是初始化程序赋值。该赋值发生在该行代码实际 执行 时(同样,这与变量在技术上 created[=69= 的时间点不同) ]).

所以,快速回顾一下:

  • All 变量声明(使用 var)在初始化时 总是undefined 初始化他们的词汇环境。
  • 这个初始化在技术意义上可能不算作赋值(哈,@ThisClark,你错了! !)。 :)
  • 分配是比较简单的部分,因为它们的行为方式(以及在时间点上)符合您的预期。

希望对您有所帮助(而且我没有严重误解规范!)。

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

var test;        // Is this a declaration ?

初始化指的是一个值的"assignment"。

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

直接取自 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.

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

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

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

我目前不知道也无法测试的是,在网络浏览器历史记录中,警报会显示多长时间。例如,此警报在 IE6 或某些晦涩的黑莓 phone 中是否有效?我不能肯定地说这是通用的,但它至少适用于最新版本的 Firefox Chrome 和撰写本文时的 Safari。

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

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

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

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

所有变量的默认值(如果没有明确提及则未定义)

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"

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

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

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

例如假设第 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)  }

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

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

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


基本思路

  • 'Declaration' 使变量在给定范围内可用。
  • 'Assignment' 在代码中的那个位置给变量一个特定的值。如果您尝试为从未在该作用域或父作用域中声明的变量赋值,则该变量将在全局作用域中隐式声明(等于键入 window.varName = value)。
  • 'Initialization' 可以说是 'behind the scenes' 或 'under the hood' 发生的事情。在运行时,所有声明的变量都是初始化的赋值undefined(甚至如果他们立即在第一行代码中被分配了不同的值)。

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

所以直接回答你问题中的例子:

  • var example; 声明了一个变量,它在初始化期间被赋值为 undefined
  • var example = "hi" 声明了一个变量,它最初也被分配了一个值 undefined,但是当在执行过程中实际到达该行代码时,它被重新分配给字符串 "hi".


示例代码

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'.
}


'Scope' 对 Declaring/Assigning

的影响

声明和赋值之间的区别更加明显的是声明一个变量总是在当前范围内创建一个新变量(myVar scopeB),即使父作用域中已经存在同名变量(myVarscopeA)。然后我们可以分配一个新值给myVarscopeB在当前的任何一点范围而不重新声明它。 (这个赋值不影响myVarscopeA的值。) 一旦scopeB 已达到,myVarscopeB 将不再可用于分配。

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

因此,一个变量只需要声明一次每个作用域,每个声明覆盖父作用域中的任何声明(即它创建一个不同的变量)。但它 必须 在范围内声明,如果它意味着在该范围内是唯一的。赋值可以根据需要发生多次,但只会影响最多的 'closely-declared' 变量(因为缺少更好的术语)。

Declaration: Variable is registered using a given name within the corresponding scope (e.g., inside a function).

Initialization: When you declare a variable it is automatically initialized, which means memory is allocated for the variable by the JavaScript engine.

Assignment: This is when a specific value is assigned to the variable.

let x; // Declaration and initialization
x = "Hello World"; // Assignment

// Or all in one
let y = "Hello World";

来源:SitePoint