【问题标题】:Declaring vs Initializing a variable?声明与初始化变量?
【发布时间】:2015-07-30 02:50:53
【问题描述】:

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

var example; // this is declaring

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

我不认为我是正确的,但每个人的确切定义是什么?还是它们的意思基本相同?

【问题讨论】:

  • 1.声明example,定义并赋值给undefined。 2、声明example,定义为String,赋值给"hi"

标签: javascript variable-declaration variable-initialization


【解决方案1】:

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

这是除specification 之外的信息:

var 语句声明了范围为正在运行的执行上下文的 VariableEnvironment 的变量。 var 变量在实例化它们包含的词法环境时创建,并在创建时初始化为undefined。 [...] 由具有 Initializer 的 VariableDeclaration 定义的变量在执行 VariableDeclaration 时分配其 Initializer 的 AssignmentExpression 的值,而不是在创建变量时。

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

  • 变量声明(例如,var foo)会在“词法环境”被实例化后立即创建该变量。例如,如果该变量是在函数体中定义的,那么该函数就是“词法环境”,因此变量的创建与函数本身的实例化是一致的。

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

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

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

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

  • 1234563对函数本身的运行时语义没有影响(无论是否发生任何实际分配或对foo 的其他引用)。如果这仍然令人困惑,请重新阅读前面的要点。
  • 最后一点行为是最直观的部分,这就是 initializerassignment。当该行代码实际执行时,就会发生这种分配(同样,这与变量在技术上创建的时间点不同)。

所以,快速回顾一下:

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

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

【讨论】:

  • 因为是javascript,所以变量声明也赋值undefined
  • 看到了吗?规格并不那么难以理解。 ;-)
  • @jmar777 非常感谢。实际上,回顾点很有帮助,因为我没有试图理解“太深的技术术语”! :)
  • 这是真的。对于在创建时赋予声明变量的初始值,我应该说 initialize 而不是 assign
【解决方案2】:

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


基本理念

  • “声明”使变量在给定范围内可用。
  • “赋值”在代码中的该位置为变量提供特定值。如果您尝试为从未在该作用域或父作用域中声明过的变量赋值,则该变量将在全局作用域中隐式声明(等同于键入window.varName = value)。
  • “初始化”是发生在“幕后”或“幕后”的事情,可以这么说。在运行时,所有声明的变量都初始化,开始赋值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'.
}


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

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

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

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

【讨论】:

  • 用适当的代码示例块很好地解释了......!谢谢
  • 这是一个绝妙的答案!
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

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

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

    //equivalent expressions
    var ex1;
    var ex2 = undefined;
    
    //true!
    alert(ex2 === ex1);

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

    【讨论】:

    • 它总是有效的。在ecma-international.org 上提供了以前版本的ECMAScript 规范。 Ed 1 §10.2.3,bullet 3 说:“对于代码中的每个 VariableDeclaration,创建一个变量对象的属性,其名称是 VariableDeclaration 中的 Identifier,其值未定义......”。 ;-) 在这种情况下,undefined 表示原始未定义值,(不是“未定义”)。
    【解决方案5】:

    唯一的区别是var 语句将将所有声明的变量初始化为undefined

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

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

    【讨论】:

    • 不需要加粗,所有声明的变量在创建时都初始化为undefined
    【解决方案6】:

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

    所有变量的默认值(如果没有明确提到就是未定义)

    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:这只是一个简单的用法示例。

    【讨论】:

    • 将变量声明放在其作用域的顶部也是很常见的,即使它们的值直到稍后才被分配。其他人喜欢在第一次使用它们的代码块或代码段之前立即声明它们。这完全是风格问题。
    • 是的,大多数时候都是风格问题,有时也需要,如示例中所述。
    【解决方案7】:

    声明:使用给定名称注册变量 相应的范围(例如,在函数内部)。

    初始化:当你声明一个变量时,它会自动 初始化,这意味着内存被分配给变量 JavaScript 引擎。

    赋值:这是将特定值分配给变量的时候。

    let x; // Declaration and initialization
    x = "Hello World"; // Assignment
    
    // Or all in one
    let y = "Hello World";
    

    来源:SitePoint

    【讨论】:

      【解决方案8】:

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

      var test;        // Is this a declaration ?
      

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

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

      【讨论】:

      • 因为是javascript,变量声明也赋值undefined
      • 不完全是。 “初始化”是在引擎准备一切的运行时发生的事情。在初始化期间,分配了一个初始值undefined。正如您所说,您答案中的第二个示例实际上是“赋值”,但是由于变量可以多次分配新值,因此重要的是要注意,每次赋值时它都不会被“初始化”。它只被初始化一次。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多