【问题标题】:In Javascript, can I use a variable before it is declared?在 Javascript 中,我可以在声明变量之前使用它吗?
【发布时间】:2013-11-26 15:12:36
【问题描述】:

我一直想知道是否可以在定义之前在 JS 中使用变量, 例如:

var country = "USA";
switch (country) {
    case "USA":
        country = i;
    case "blach":
        //not finished yet
}
/*
  put a whole
  bunch more code here
*/
var i = 10;

这有效吗?是否允许?如果是这样,它的技术术语是什么?

【问题讨论】:

  • 对不起,但我觉得这个问题并没有“显示出足够的研究努力”。 Variable scope 是基本的编程知识。简单地运行有问题的代码应该证明这是允许的。问题可能是“在声明变量之前使用变量的技术术语是什么”。随意编辑问题,反对票可能会消失。我会指出,即使this JavaScript 问题也没有提到 hoisting

标签: javascript variables scope switch-statement


【解决方案1】:

这是一种被称为hoisting 的JavaScript 引擎使用的技术。解析器将在运行之前通读整个函数,并且任何变量声明(即使用var 关键字)都将被执行,就好像它们位于包含范围的顶部一样。所以你的代码表现得像:

var country;
var i;

country = "USA";
switch (country) {
case "USA":
    country = i;
case "blach":
    //not finished yet
}

i = 10;

所以,i 在整个范围内声明,但在i = 10 语句运行之前,它的值是undefined

在 ECMAScript 术语中,当调用函数时,函数的新词法范围会在函数的任何代码运行之前构建其 VariableEnvironment。在ECMAScript 10.5, step 8:

8。对于 code 中的每个 VariableDeclaration...d,按源文本顺序执行

一个。设 dn 为 d 中的标识符。

...

我。调用 env 的 CreateMutableBinding 具体方法,传递 dnconfigurableBindings 作为参数。

二。调用 env 的 SetMutableBinding 具体方法,传递 dnundefinedstrict 作为参数。

这倒是挺拗口的,但基本上是在说:

在运行函数之前,请查看函数的源代码中的声明,例如 var [identifierName]

对于您找到的每个声明,在函数的作用域中创建一个新变量,名称为声明中使用的 [identifierName],然后将其值设置为 undefined

【讨论】:

  • 很高兴您为此添加了对 10.5.8 +1 的引用 :)
【解决方案2】:

它被称为variable hoisting,这是一个很好理解的概念,因为它偶尔会产生难以追踪的错误

例如:

var stuff = 'stuff';
function() {
 console.log(stuff); //outputs 'undefined'
 var stuff = 'other stuff';
 console.log(stuff); //outputs 'other stuff'
}

第一个 console.log 输出 undefined 因为函数中的 var stuff提升到函数顶部。

//theoretical compiled output
var stuff = 'stuff';
function() {
 var stuff; //has not been defined
 console.log(stuff);
 stuff = 'other stuff'; //defined here
 console.log(stuff);
}

如果不了解变量提升,这个结果可能会令人困惑。

因此,如果您查看专业开发的 JavaScript 代码,通常会看到函数中的所有变量都声明在顶部。

【讨论】:

    【解决方案3】:

    是的。在 JavaScript 中,变量是hoisted

    variable 语句声明按照10.5 中定义创建的变量。 变量在创建时初始化为未定义在执行 VariableStatement 时而不是在创建变量时为具有 Initialiser 的变量分配其 AssignmentExpression 的值。ES5 §12.2
    其中 10.5第8步是感兴趣的部分

    【讨论】:

      【解决方案4】:

      这些家伙的答案是正确的。对于您的示例,值得注意的是countryundefined。正如 aspillers 所提到的,您的代码行为如下

      var country;
      var i;
      
      country = "USA";
      
      switch (country) {
      case "USA":
          country = i;
      case "blach":
          //not finished yet
      }
      
      i = 10;
      alert(country) //undefined;
      

      但是当您的 case 语句针对“美国”运行时,i 未定义,因此将其分配给 country。在fiddle 中尝试一下。

      我猜你只需要注意,虽然变量声明被提升了,但值分配没有。

      【讨论】:

      • 我是JS 的新手,所以我不太了解。请原谅,但我的理解是hoisting 意味着无论var 在哪里,都可能在当前范围内;它将在开始执行之前分配内存。那为什么这个变量是未定义的?
      • @VikasBansal - 仅提升引用。值的分配没有提升。因此,在 switch 语句中的示例 country = i 只是将 undefined 分配给国家,因为 i 的值是在末尾分配的
      猜你喜欢
      • 2020-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      相关资源
      最近更新 更多