Javascript 提升和变量赋值(没有声明)

Javascript hoisting and variable assignment (with no declaration)

查看 MDN's introduction to JavaScript, Grammar and Types section - 一个是:

Declaring variables

You can declare a variable in three ways:

  • With the keyword var. For example, var x = 42. This syntax can be used to declare both local and global variables.
  • By simply assigning it a value. For example, x = 42. This always declares a global variable. It generates a strict JavaScript warning. You shouldn't use this variant.
  • With the keyword let. For example, let y = 13. This syntax can be used to declare a block scope local variable. See Variable scope below.

以下代码片段似乎适合 "by simply assigning it a value" 场景,这意味着该变量应被视为全局变量。

(function(){
   console.log(myVar);
   //the following will throw a ReferenceException error
   //myVar = 10;

   //the following will not, and I can understand it following the defintion of the behavior of using `var` keyword
   //var myVar = 10;
})();

但是 运行 当 myVar 被注释时,代码将生成一个 ReferenceException,而当没有被注释时,代码将生成一个 ReferenceException。我希望它在这两种情况下都会生成 undefined ,因为如果 myVar 是一个全局变量(根据定义),那么 javascript 的变量提升会在到达 console.log(myVar);

这种行为背后的解释是什么? (我描述的行为是我在我的 firefox 控制台中尝试时得到的,但是 运行 它在 jsfiddle 中不会抛出错误)。

自执行函数是提升的例外吗?

the "by simply assigning it a value" scenario

您正在读取值,而不是分配它

if myVar is a global variable (per definition),

不是。

myVar 是:

  • 作用域为函数的变量 如果函数包含 var myVar(或 function myVar () { ... },或者在函数定义中作为参数列出) .
  • 如果块包含let myVar
  • ,则变量作用域为块
  • 一个全局变量 如果之前已经给它分配了一个值并且以上条件都不成立。

由于您尚未分配值,因此它不是全局值。由于上述条件 none 为真,它不是任何类型的变量,所以你得到一个引用错误。


关于您的评论:

I left my var when I meant var in the scenario I am trying to depict. Updated question.

…和the edit to which you refer:

注释掉的代码未被评估。使用关键字 var 的评论没有任何作用。


关于您的进一步编辑。

如果您尝试在变量声明之前读取它,则会出现引用错误。

var 语句(和函数声明)被提升,因此可以在函数中的任何位置读取使用这些方法声明的变量。

分配未提升。通过赋值隐式创建的全局变量(通常不被认为是最佳实践,在严格模式下被禁止)在赋值之前无法读取。

由于我的评论似乎有助于向您解释,我将其转化为答案:

隐式全局变量创建(当您实际上没有声明它,而只是分配给它时)未被提升。变量创建发生在赋值发生的那一刻。

因此,当您尝试读取变量时,它还不存在,这是一个错误。

varlet 声明被提升到其适当范围的顶部。


所有这些应该有助于解释为什么你应该 运行 在 strict 模式下隐式全局创建是非法的并且不允许并立即触发错误。它基本上是邪恶的。一个简单的错误拼写变量可能不会在您真正想要它时触发错误。