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

Javascript hoisting and variable assignment (with no declaration)

查看MDN对JavaScript,语法和类型部分的介绍 - 一篇内容如下:

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.

以下代码片段似乎适合"通过简单地为其赋值"方案,这意味着该变量应被视为全局变量。

1
2
3
4
5
6
7
8
(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,否则将生成undefined。 我希望它在两种情况下都生成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,则变量作用于块的变量
  • 如果先前已为其分配了值,并且上述条件都不为真,则为全局变量。

由于您尚未分配值,因此它不是全局值。由于以上条件均不属实,因此它不是任何类型的变量,因此您会收到引用错误。

关于你的评论:

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

...以及您引用的编辑:

注释掉的代码不会被评估。使用关键字var的注释不会执行任何操作。

关于您的进一步编辑。

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

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

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


由于我的评论似乎有助于向您解释,我将把它变成一个答案:

隐式全局变量创建(当您实际上没有声明它,但只是分配给它时)不会被提升。变量创建在赋值发生时内联发生。

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

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

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