Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/434.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript重新声明的全局变量覆盖旧值_Javascript_Global Variables_Scope - Fatal编程技术网

Javascript重新声明的全局变量覆盖旧值

Javascript重新声明的全局变量覆盖旧值,javascript,global-variables,scope,Javascript,Global Variables,Scope,前几天我遇到了一个有趣的问题,我想知道是否有人能解释为什么会发生这种情况。以下是我正在做的事情(为了本例的目的,我稍微简化了示例): 我正在使用方括号符号创建一个全局范围的变量,并给它赋值 后来我声明了一个与我刚才创建的变量同名的变量。注意我没有赋值。由于这是同一变量的重新声明,因此不应按此处所述覆盖旧值: 问题是旧值实际上会被覆盖,在上面的示例中,警报显示“new”而不是“old”。为什么? 我想另一种表达我的问题的方式是,上述代码在语义上与下面的代码有何不同: //create glo

前几天我遇到了一个有趣的问题,我想知道是否有人能解释为什么会发生这种情况。以下是我正在做的事情(为了本例的目的,我稍微简化了示例):

  • 我正在使用方括号符号创建一个全局范围的变量,并给它赋值
  • 后来我声明了一个与我刚才创建的变量同名的变量。注意我没有赋值。由于这是同一变量的重新声明,因此不应按此处所述覆盖旧值:

  • 问题是旧值实际上会被覆盖,在上面的示例中,警报显示“new”而不是“old”。为什么?

我想另一种表达我的问题的方式是,上述代码在语义上与下面的代码有何不同:

//create global variable 
var y = 'old';

//redeclaration of the same variable
var y;

if (!y) y = 'new';

alert(y); //shows Old
更新1:根据一些评论和答案,我重新表述了示例,以更好地反映我的原始问题

创建2个包含以下内容的javascript文件: 脚本1

脚本2

//redeclaration of the same variable
var y;

if (!y) y = 'new';

alert(y); //shows New instead of Old in IE
在html文件中包含这两个文件

<html>
 <head></head>
 <body>

  <script type="text/javascript" src="my.js"></script>
  <script type="text/javascript" src="my2.js"></script>

 </body>
</html>

在Firefox中打开此页面,Chrome会提醒“old”,这是预期的行为。然而,在IE 8中,页面实际上会提醒“新建”


更新2问题移到这里:

当您使用
var y重新声明
y
,现在它是未定义的,因此如果(!undefined)的计算结果为true,则

:

var
不会两次初始化变量,但会覆盖第一次未初始化的变量(因为它是一个新的、更局部的变量),
window['y']
样式会这样做,将其添加到window对象中。以此为例:

//create global variable with square bracket notation
window['y'] = 'old';

//redeclaration of the same variable
var y;
alert(y); //undefined

alert(window.y); //old

if (!y) y = 'new';

alert(y); //shows New instead of Old
alert(window.y);​ //still old
在JS中,不能在同一范围内“重新声明”这样的变量

var x = "foo"
function a()
{
  alert(x); // undefined
  var x;
}
在函数
a
中,变量
x
是本地变量,因为它具有
var x
。无论是在使用之前还是之后

同样地:

function b()
{
  var z = 1;
  if (true)
  {
    var z = 2;
  }
  alert(z); // 2
}

因为也没有“块”范围。

var
语句是提升的主题,这意味着当代码(就在实际运行之前)时,
var
函数
语句可用于其封闭范围

您的代码的计算结果如下:

第一个例子:

var y;
window['y'] = 'old';

if (!y) y = 'new';

alert(y);
第二个例子:

var y;
y = 'old';

if (!y) y = 'new';

alert(y);
挂起
var
语句后,您可以看到代码的实际行为

另见:


    • ?我刚刚测试了你的代码,它显示“old”,我测试了FF、Chrome、Safari(PC)和IE8



      看看这里:

      如果这是真的,为什么第二段代码没有做同样的事情。第二段代码提醒“old”而不是“new”。我正在试图理解您所说的“var不会两次初始化变量,但会覆盖第一次未初始化的变量,正如window['y']样式所做的那样,并将其添加到window对象中。”这是否意味着window.y和y是不同的对象。我认为(可能是错误的)执行window.y或window['y']意味着创建一个名为y的全局变量。@Yousuf-这就是区别,
      var y
      window.y
      不同,它们是独立的变量,
      var y
      是范围中两个变量中更局部的一个。@Yousuf-您可以直接访问它,像这样:
      window['y']='new';警报(y)
      如果没有同名的局部变量,那么您将获得该局部变量。​@优素福-有规范本身(取决于您运行的版本,取决于浏览器)…但我建议这样做,以便更实际地描述您在这里遇到的各种情况:最后一条语句并不完全正确,您可以使用
      let()
      来获得块范围。您可以重新声明它,如果重新声明发生在同一范围级别<代码>var x=“foo”;var x;警报(x)@Nick,没错,但我将自己局限于所有主流浏览器实现的JavaScript子集@Matthew,你希望它显示什么?@Nick,
      let
      是一个专有的Mozilla扩展,它只能在他们的JavaScript(TM)1.7引擎(SpiderMonkey,Rhino)@CMS上工作-我不会称之为“专有”(因为它在1.7规范中),Mozilla正式管理javascript…他们的引擎通常在其他引擎之前支持新的规范,或者出于同样的原因,这里就是这样。是的,如果第一个代码段在全局范围级别运行,
      window['y']
      相当于
      var y
      ,因此它会提醒旧代码。JSFIDLE不是在全局范围内运行,而是在函数中运行。也许优素福的原始代码也在函数中。请参阅查看源代码:为什么在函数内部执行window['y']='old'与在全局范围内执行不同?优素福,
      window['y']
      是相同的。不同的是
      vary
      (在一个函数中,
      vary
      创建一个新变量来隐藏全局变量,除非您使用
      window
      ),JSFIDLE让您“新建”是很奇怪的。我只是在本地创建了一个普通的HTML页面来测试这一点,当它直接从一个页面开始时,我仍然会得到“old”。@Matthew-对,但是var y是直接在脚本文件中声明的。它不在函数中。这就是我想表达的观点。既然它不在函数中,那么为什么它会覆盖旧值(因为它应该被视为一个重新声明,除非根据Nick的回答,这是两个不同的变量)你简化的部分一定是所有这些代码都在一个函数中的地方,给var y一个不同于window的范围。YY你的更新应该是一个新问题,特别是因为它是特定于浏览器的。我不认为提升是跨文件进行的,但我认为这是有意义的,因为它们在同一范围内执行。Afte
      function b()
      {
        var z = 1;
        if (true)
        {
          var z = 2;
        }
        alert(z); // 2
      }
      
      var y;
      window['y'] = 'old';
      
      if (!y) y = 'new';
      
      alert(y);
      
      var y;
      y = 'old';
      
      if (!y) y = 'new';
      
      alert(y);