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
语句(和函数声明)被提升,因此可以在函数中的任何位置读取使用这些方法声明的变量。
分配未提升。通过赋值隐式创建的全局变量(通常不被认为是最佳实践,在严格模式下被禁止)在赋值之前无法读取。
由于我的评论似乎有助于向您解释,我将其转化为答案:
隐式全局变量创建(当您实际上没有声明它,而只是分配给它时)未被提升。变量创建发生在赋值发生的那一刻。
因此,当您尝试读取变量时,它还不存在,这是一个错误。
var
或 let
声明被提升到其适当范围的顶部。
所有这些应该有助于解释为什么你应该 运行 在 strict
模式下隐式全局创建是非法的并且不允许并立即触发错误。它基本上是邪恶的。一个简单的错误拼写变量可能不会在您真正想要它时触发错误。
查看 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
语句(和函数声明)被提升,因此可以在函数中的任何位置读取使用这些方法声明的变量。
分配未提升。通过赋值隐式创建的全局变量(通常不被认为是最佳实践,在严格模式下被禁止)在赋值之前无法读取。
由于我的评论似乎有助于向您解释,我将其转化为答案:
隐式全局变量创建(当您实际上没有声明它,而只是分配给它时)未被提升。变量创建发生在赋值发生的那一刻。
因此,当您尝试读取变量时,它还不存在,这是一个错误。
var
或 let
声明被提升到其适当范围的顶部。
所有这些应该有助于解释为什么你应该 运行 在 strict
模式下隐式全局创建是非法的并且不允许并立即触发错误。它基本上是邪恶的。一个简单的错误拼写变量可能不会在您真正想要它时触发错误。