简体   繁体   English

为什么此代码不会导致ReferenceError?

[英]Why does this code not result in a ReferenceError?

if(true) {
  tmp = 'abc';
  console.log(tmp);//which should throw referenceError but not

  let tmp;
  console.log(tmp);

  tmp = 123;
  console.log(tmp);
}

This code results in 此代码导致

abc
undefined
123

Why does the first console.log(tmp) not throw an error? 为什么第一个console.log(tmp)不会引发错误?


why it should throw a referenceError 为什么它应该抛出referenceError

In ECMAScript 2015, let will hoist the variable to the top of the block. 在ECMAScript 2015中,让我们将变量提升到块的顶部。 However, referencing the variable in the block before the variable declaration results in a ReferenceError. 但是,在变量声明之前在块中引用变量会导致ReferenceError。 The variable is in a "temporal dead zone" from the start of the block until the declaration is processed. 从块的开始直到声明被处理,该变量位于“临时死区”中。


the problem is bable settings,i think. 我认为问题是圣经的设置。
so,maybe it is a bug of babel? 所以,也许这是通天的虫子吗? https://github.com/babel/babel.github.io/issues/826 https://github.com/babel/babel.github.io/issues/826

You are correct, in ES6 this does throw an exception. 您是正确的,在ES6中确实会引发异常。 There's two reasons why it doesn't for you: 为什么不适合您有两个原因:

  • node.js already implemented let - but it works correctly only in strict mode. node.js中已经实现了let -但它只能在严格模式下正常工作。 You should use it. 您应该使用它。
  • babel does not appear to transpile the TDZ by default, as it is quite complicated and leads to lengthy code. babel在默认情况下似乎不会转译TDZ,因为它相当复杂并导致冗长的代码。 You can however enable it with the es6.blockScopingTDZ / es6.spec.blockScoping option (but I'm not sure whether this worked in Babel 5 only and what happened in Babel 6 to them). 但是,您可以使用es6.blockScopingTDZ / es6.spec.blockScoping选项启用它(但是我不确定这是否仅在Babel 5中起作用,以及在Babel 6中发生了什么)。

Statement 声明

tmp = 'abc';

is not elegant but still OK in normal mode ( except let keyword which is not allowed outside strict mode ). 不是很优雅,但在正常模式下仍然可以( 除非在严格模式下不允许使用let关键字 )。 It will simply create global variable. 它只会创建全局变量。 However, the code is not correct and will throw an error only when you executed this code in "strict mode". 但是,该代码不正确,只有在“严格模式”下执行此代码时,才会引发错误。 In this mode you have to declare all variables with one of this keywords: 在这种模式下,您必须使用以下关键字之一声明所有变量:

  • var VAR
  • let
  • const 常量

 'use strict' if(true) { tmp = 'abc'; console.log(tmp);//which should throw referenceError and now it does let tmp; console.log(tmp); tmp = 123; console.log(tmp); } 

No, it shouldn't throw a reference error. 不,它不应引发参考错误。

The variable is implicitly declared (in the global scope) when you assign to it. 分配给变量时,会在全局范围内隐式声明该变量。

Then, later, you declare a new variable with the same name but a tighter scope. 然后,稍后再声明一个具有相同名称但作用域更严格的变量。 The new variable is not hoisted because it is declared using let . 由于使用let声明了新变量,因此未将其挂起。

I can't give a more precise answer, because you did not explain why you think you should get a reference error. 我无法给出更准确的答案,因为您没有解释为什么您认为应该得到参考错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM