Javascript和变量赋值(无声明)

Javascript和变量赋值(无声明),javascript,hoisting,Javascript,Hoisting,看看——其中一条是: 声明变量 可以通过三种方式声明变量: 使用关键字var.例如,var x=42。此语法可用于声明局部变量和全局变量 只需给它赋值。例如,x=42。这总是声明一个全局变量。它生成一个严格的JavaScript 警告你不应该使用这个变体 使用关键字let。例如,设y=13。此语法可用于声明块作用域局部变量。参见变量范围 下面 下面的代码片段似乎适合“通过简单地给它赋值”的场景,这意味着变量应该被视为全局变量 (function(){ console.log(myVar

看看——其中一条是:

声明变量 可以通过三种方式声明变量:

  • 使用关键字var.例如,var x=42。此语法可用于声明局部变量和全局变量
  • 只需给它赋值。例如,x=42。这总是声明一个全局变量。它生成一个严格的JavaScript 警告你不应该使用这个变体
  • 使用关键字let。例如,设y=13。此语法可用于声明块作用域局部变量。参见变量范围 下面
下面的代码片段似乎适合“通过简单地给它赋值”的场景,这意味着变量应该被视为全局变量

(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,否则将生成一个未定义的引用异常。我希望它在这两种情况下都会生成未定义的,因为如果
myVar
是一个全局变量(根据定义),那么javascript的变量提升将在到达
console.log(myVar)之前让它知道

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

自动执行功能是否为提升的例外

“通过简单地分配一个值”场景

您正在读取值,而不是赋值

如果myVar是一个全局变量(根据定义)

事实并非如此

myVar
是:

  • 如果函数包含
    var myVar
    (或
    function myVar(){…}
    ,或在函数定义中作为参数列出),则该变量的作用域为函数
  • 如果块包含
    let myVar
  • 全局变量,前提是之前已为其赋值,且上述条件均不成立
由于尚未指定值,因此它不是全局值。因为上面的条件都不是真的,所以它不是任何类型的变量,所以您会得到一个引用错误


关于你的评论:

在我试图描述的场景中,当我指的是var时,我留下了我的var。更新问题

……和:

未对注释掉的代码进行求值。使用关键字
var
的注释没有任何作用


关于您的进一步编辑

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

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


作业未挂起。通过赋值隐式创建的全局变量(通常不被认为是最佳做法,在严格模式下被禁止)在赋值之前无法读取。

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


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

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

var
let
声明被提升到其适当范围的顶部



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

JSFIDLE会在Firefox和Chrome中为我生成ReferenceError。隐式全局变量创建(当您实际上没有声明它,但只是分配给它时)不会被提升。它发生在赋值发生的地方。因此,当您试图读取变量时,它还不存在,这是一个错误
var
let
声明被挂起。@jfriend00:噢,jfriend00是第一个在这里提示解释它的东西(至少对我来说)。这就是答案。哎呀,我错了,我离开了var myVar,当时我只是想在我试图描述的场景中使用myVar。更新的问题。您正在读取值,而不是赋值-这意味着mdn的定义有问题,不是吗?MDN声明这是一项任务。没有事先声明,转让是不可能完成的。昆汀,注意我的第一条评论,我最初发布的代码版本不正确。我指的是注释掉这一行的版本,其他版本称为“var myVar”。@Veverke-您编辑的代码只更改了注释的内容。注释不被视为代码。这就是评论的全部要点。你说得对,我补充了困惑,再次更新了问题。我现在留下了我原本打算写的两个版本的声明。运行一个会抛出错误,另一个不会抛出错误。从使用
var
关键字声明变量的行为定义中,我可以理解这是一个可行的方法。我把你的评论挑出来,因为另一个答案没有涉及到这一点——对我来说,这似乎是唯一的答案。不幸的是,在你来之前,我发布的问题版本令人困惑,没有反映当前的情况——这就是我想问的,因此昆汀可能不知道真正的问题。虽然你是第一个添加解决方案的人,但在他将这一点也包括在自己的报告中之后,我会为他的努力选择昆汀的答案。