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

时间:2016-05-01 15:02:38

标签: javascript hoisting

查看MDN's introduction to JavaScript, Grammar and Types section - 其中一条写着:

  

声明变量

     

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

     
      
  • 使用关键字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,否则将生成undefined。我希望它在两种情况下都生成未定义,因为如果myVar是一个全局变量(根据定义),那么javascript的变量提升会在到达console.log(myVar);

之前知道它

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

自动执行功能是提升的例外吗?

2 个答案:

答案 0 :(得分:7)

  通过简单地为其分配一个值""方案

正在阅读值,而不是分配

  

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

不是。

myVar是:

  • 如果函数包含var myVar(或function myVar () { ... },或者它在函数定义中作为参数列出),则作用于函数的变量。
  • 如果块包含let myVar
  • ,则作用于块的变量
  • 一个全局变量如果先前已为其分配了值,则上述条件均不为真。

由于您尚未分配值,因此它不是全局的。由于上述条件均不属实,因此不存在任何变量,因此会出现参考错误。

关于你的评论:

  

当我在我试图描绘的场景中使用var时,我离开了我的var。更新的问题。

...和the edit to which you refer

未评估已注释掉的代码。使用关键字var的评论不会做任何事情。

关于您的进一步修改。

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

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

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

答案 1 :(得分:1)

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

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

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

varlet声明被提升到相应范围的顶部。

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