为什么临时死区存在?

时间:2017-03-10 12:17:31

标签: javascript

我知道what is the temporal dead zoneTDZ),但我无法理解它存在的目的。

任何人都可以解释为什么它被创造出来了吗?

提出ReferenceErrorSyntaxError而不是返回undefined的逻辑是什么?

的ReferenceError:

console.log(typeof foo);
let foo;

语法错误:

let foo;
let foo;

未定义:

console.log(typeof foo);

4 个答案:

答案 0 :(得分:2)

在初始化之前使用变量始终是一个错误。使这个错误是合理的,因为它有助于开发人员注意到他们的错误并能够修复它。 varundefined开头的行为已经导致了太多问题,如果将const变量或静态类型注释用于相似的语义,它们会变得更糟。

答案 1 :(得分:2)

从定义变量开始就存在变量是有意义的。由于外部作用域中的变量可以在嵌套作用域内访问,因此以下代码非常混乱:

var foo = 'out';

function bar () {
  foo = 'in';
  console.log(foo);
  var foo;
}

bar();

bar()函数有什么作用?它创建了一个名为foo的新变量,并在它显示在控制台中之前为其分配'in'。之后,来自外部范围的变量仍然等于'out'。因此,在使用变量之前定义变量是一个更聪明的事情。我相信你可以在声明之前使用变量只是一个实现简单和效率的问题,但我在这里大胆猜测。

但是,在JS中,使用var关键字创建的变量可以从其函数中访问,而不是从中访问。这允许更宽松的语法,如下所示:

function setGameMode (mode) {
  if (mode === 'peaceful') {
    var count = 0;
    for (var i = 0; i < mobs.length; ++i) {
      if (mobs[i] instanceOf EvilMob) {
        mobs[i].despawn();
        ++count;
      }
    }
    console.log('Removed ' + count+ ' evil mobs out of ' + i);
    mobSpawner.evil = false;

  } else if (mode ==='chaotic') {
    var count = 0;
    for (var i = 0; i < mobs.length; ++i) {
      if (mobs[i] instanceOf NiceMob) {
          mobs[i].despawn();
          ++count;
      }
    }
    console.log('Removed ' + count + ' nice mobs out of ' + i);
    mobSpawner.nice = false;
  }
}

由于函数范围的变量,{for循环后i变量仍然存在。这也是var关键字允许您定义变量两次的原因。如果你被迫只写一次var,那就不切实际了。使用let变量时,这个“松散”功能变得毫无用处,因为这些变量应该在不再需要时立即释放。

当您在大多数编程语言中调用函数时,执行环境会在内存中为您需要的变量创建一个空间。在这里,没有办法在不实际运行代码的情况下判断是否需要变量i,因为它位于if块内。但是,由于JS具有函数范围的变量,因此必须从函数的开头创建变量。在let变量的情况下,不需要这样做。

至于typeof someundefinedvar返回'undefined'背后的原因,那是因为你需要一种方法来检查可能已经在外部范围内声明的变量。但是,对于块作用域的变量,您不需要该功能。 let变量意味着立即使用并丢弃。

答案 2 :(得分:0)

  1. console.log(typeof a); let a;
  2. 在上面的陈述中,您没有定义变量a,而您正在使用它。在java脚本中,有必要定义一个变量。该变量是您的值的参考因此,这就是为什么显示未定义的参考错误。

    1. let a; let a;
    2. 在第二个语句中,您已经定义了两次变量。 js不允许您将任何变量多次定义到相同的块范围内。

      1. console.log(typeof foo);

        在第3个语句中,因为它在第一个函数中显示错误,即您的变量未定义。默认情况下,它是未定义的。你可以使用未定义的变量。

答案 3 :(得分:0)

如果你检查了你在问题中链接的那些例外的文档,你可以看到为什么,我认为这里没有提到。

首先要注意的是:值得一提的是,在版本3之前,EMCAScript中不存在例外情况.var显然早于这种语言功能。 为什么 var和let不同主要是因为引入let时异常可用,而不是在引入var时。这段历史强调了这一切。 1999年也是忙碌的一年!

无论如何,进入齿轮。看看这里发生了什么:

// example A
(function () {
console.log(somethingUndefined - 1);
var somethingUndefined;
console.log('another operation');
})();

错误,然后代码继续。我们可以抓住这个并处理它吗?

// example B
(function () {
try {
    console.log(somethingUndefined - 1);
    var somethingUndefined = 50;
    console.log('another operation');
} catch (e) {
    console.log('I want to deal with problems here');
    return;
}

console.log('plowing on');
})();

不。

在幕后,此代码如下所示:

// example C
(function () {
var somethingUndefined = undefined;
try {
    console.log(somethingUndefined - 1);
    somethingUndefined = 50;
    console.log('another operation');
} catch (e) {
    console.log('I want to deal with problems here');
    return;
}

console.log('plowing on');
})();

没有“暂时死区”,因为例B和B中没有任何意义。 C变量somethingUndefined不是什么的。这是一种“未定义”,somethingUndefined === undefined,这不是什么都没有。然后它是50,但为时已晚,无法发挥作用。有用与否,我们可以用它来做事,因为它有价值。第1行,第8行,它始终具有某些值。比较输出的差异:

// example D
(function () {
try {
    console.log(somethingUndeclared - 1);
    console.log('another operation');
} catch (e) {
    console.log('I want to deal with problems here');
    console.log(e);
}
})();

在示例D中的每一点,somethingUndeclared都不算什么。这是一个永远死亡的区域。我不确定上面的代码开始抛出异常的哪个EMCAScript版本,但它不会因此而破坏,因为这种情况总是会出错。

除非在同一范围的某些其他部分或父范围somethingUndeclared已定义,否则可能出于某些其他目的。或者代码var somethingUndeclared;可能由于某种原因而在范围或父范围内的某处放置,因此在上面的代码中没有抛出任何异常。这是几乎完全使用let或const的论据。

当你使用let或const时,有一个“死区”,一个什么时候它不是什么东西,那么它就是某种东西。它不是undefined,等待发生是一个例外。在let语句到达之前,它就像一个未声明的变量,抛出异常,然后在声明行中它就像一个带有值的var。它是var的行为与未声明变量的结果的混合。

// example D
(function () { // temporal dead zone, something is nothing
try { // temporal dead zone, something is nothing
    console.log(something - 1); // exceptional behavior! temporal dead zone
    let something  = 50; // temporal live zone begins here!
    console.log('another operation');
} catch (e) {
    console.log('I want to deal with problems here'); // you could call this a dead zone
    console.log(e); // dead
}
// dead
})(); // way dead

这让我们接受了乞求的问题,“为什么不拉开乐队,为了语言的一致性而处理BC休息?”答案是因为足够好就足够了。有数百万行javascript管理手风琴和图像画廊以及其他UI铃声和口哨声。当EMCAScript填补关键任务角色时,可以选择更成熟的一组语言功能。或者你只是不喜欢草率的代码为您的甜选项卡导航。语言的一致性并不值得打破所有代码,这些代码足以完成大多数时间所需的代码。想象一下已经积累的足够好的山脉,因为它甚至可以用这种语言抛出异常('99)。

当我们需要它做它应该做的事情时,我们可以利用这些功能。当undefined = 100;成为项目中某个文件的灾难时,我们可以选择加入异常。当渐进增强失败并且我们没有工具提示时,我们有一个不太好的用户体验,而不是我们希望的。我们肩膀上有不同的历史和不同的重量,所以他们可能总是采取不同的行动。