提升未声明'var'的JS变量
Hoisting of JS variables declared without 'var'
我正试图让我的头在JavaScript中提升和作用域,我试图弄清楚到底发生了什么在这段代码。正如我所料,console.log(outside)
和console.log(local)
都是未定义的,因为outside
被声明但未初始化,而local
的声明被提升到函数的顶部。但是为什么typeof global
等于'undefined'
呢?在函数中省略var
与在全局范围内声明变量相同-在哪种情况下它不会被提升?
var outside;
(function() {
i = 2;
if (i == 1) {
var local = 'local';
global = 'global';
}
// Demonstrates that local variables are hoisted but global variables are not.
console.log(outside); // undefined
console.log(local); // undefined
console.log(global); // Uncaught ReferenceError: global is not defined. (i.e. typeof global === 'undefined')
})();
http://jsfiddle.net/ffjiang/sYvbL/首先,只有实际使用var
、let
或const
或函数声明定义的变量才会被提升。var
声明被提升到函数作用域的顶部。const
和let
声明被提升到包含块的顶部。虽然var
声明可以在声明之前引用(在同一个函数中),但const
和let
声明不能在声明之前使用(即使它们在技术上被提升到块的顶部)。
赋值给一个之前没有声明过的变量(当不在严格模式下运行时),在赋值发生的那一刻创建一个该名称的全局变量。这样做从来都不是好的编程。应该总是显式地声明变量。即使你想成为全局变量,也应该全局声明。
在严格模式下,您不能执行"auto-global"你只要赋值给一个不存在的变量它就会自动变成一个全局变量。在Javascript中,越来越多的代码自动进入严格模式,比如class
声明的一部分。
试图读取一个以前没有声明过的变量会导致引用错误,除非你在它前面加上一个包含对象,比如window.somevar
,在这种情况下,它会返回与任何其他不存在的对象(undefined
)的属性相同的属性。
您的代码基本上相当于以下内容(添加了一条console.log()语句):
var outside; // declared as a global
(function() {
var local; // the declaration of this variable is hoisted to here
i = 2;
if (i == 1) {
local = 'local';
global = 'global'; // creates a global variable only when this line is executed
}
console.log(outside); // undefined
console.log(local); // undefined
console.log(window.global); // undefined
console.log(global); // Uncaught ReferenceError, no symbol of this name is found
})();
这意味着outside
和local
都是在您尝试使用它们时定义的,因此没有引用错误。它们都没有被初始化,所以它们的值是undefined
。当你试图引用global
时,它没有被定义,因为你没有执行对它的赋值,所以它不存在。当您实际上没有声明全局变量时,不会提升全局变量的自动创建。这些变量只有在分配给它们的代码实际执行时才会被创建。
因为您тot给外部分配了一个值(它是未定义的)
var outside = 5; // <=outside is 5
(function() {
i = 2;
if (i == 2) { // Condition is not satisfied. So variables are not declared. Replace to i==2;
var local = 'local';
global = 'global';
}
// Demonstrates that local variables are hoisted but global variables are not.
console.log(outside); // 5
console.log(local); // local
console.log(global); // global
return true
})();
没有提升global
,因为它没有在函数体中使用var
声明;只有local
被提升。
global = 'global';
如果该语句被运行,它将隐式地创建一个全局声明,如果它还不存在。
但是它不是(run),所以当你试图引用它时,它会正确地引发ReferenceError。
如果使用var
声明变量,则声明向上传播到最近的作用域(在您的例子中是函数定义)。没有var
的变量都隐式地赋值为window
对象的属性。所以在你的例子中,global = 'global'
和window.global = 'global'
本质上是一样的。因为代码永远不会被执行,window
不会得到这个属性,当你在console.log
中访问它时,它没有定义。
- JS变量返回的对象不是值
- 我怎么能让流星简单模式中的一个字段等于一个js变量,并且仍然让用户填写简单模式的其余部分
- 向AngularJS目录添加JS变量
- 在使用cq:include包含外部JS之前,如何在JSP中包含全局JS变量
- 将PHP数组传递给js变量
- 如何从谷歌脚本中获取JS变量
- 敲除js变量设置类似于调用函数
- 带破折号的Ractive.js变量
- jQuery在MVC应用程序中设置JS变量
- HTML按钮获胜't更改JS变量
- 在跨子域上将JS变量从子Iframe传递给父JSP
- 理解bootstrap.js变量声明
- 使用HTML标记中的JS变量在Javascript中动态创建HTML
- 访问JQuery中的vue-js变量
- AJAX将JSON数组保存到多个JS变量中
- 在构造控制器、服务等时作为函数参数传递之前列出的角度 JS 变量
- 将JS变量作为文本返回以发送到Google Analytics
- 将JS变量传递到php数组
- 如何将JS变量异步发送到Rails
- 正在读取JS变量