声明提升解释
考虑下面的代码:
var myvar = 'my value';
alert(myvar); // my value
当然,它会在屏幕上弹出my value
,这是显而易见的。然而,跟着我的思路,让我们创建一个自执行匿名函数,它会达到同样的效果。
var myvar = 'my value';
(function() {
alert(myvar); // my value
})();
好吧,这还是很显而易见的,我知道,现在让我们把这两个例子的代码混合在一起,在匿名函数内部创建一个相同的变量。
var myvar = 'my value';
(function() {
alert(myvar); // undefined
var myvar = 'local value';
})();
哈,为什么alert的值是undefined
,哪怕我们声明了一个新的变量,函数执行仍然是同样的结果,所以它是没有效果的吗?
变量声明的提升
在函数的当前作用域中,无论变量声明的位置在哪里,浏览器将在后台提升知代码的头部,然而仅仅是变量的声明会被提升,而如果变量被初始化(已被赋值),仅仅变量的声明会被提升至代码的顶部,且将此变量的值设置为 undefined
好了,让我们解读一下这变量声明和变量初始化之间的差异,假设有这样的代码:var joe = 'plumber';
变量声明
var joe; // the declaration
变量初始化
joe = 'plumber'; // the initialization
现在我们可以更容易地理解变量提升操作在浏览器引擎下发生了什么,考虑下面这个伪造的函数
(function() {
var a = 'a';
// lines of code
var b = 'b';
// more lines of code
var c= 'c'; // antipattern
// final lines of scripting
})();
全部的变量声明都在代码顶部
请注意,上面的例子被认为是不好的做法。尽管如此,不管变量的位置在哪里,它们的声明都会在后台提升至代码顶部,像这样:
(function() {
var a, b, c; // variables declared
a = 'a';
// lines of code
b = 'b'; // initialized
// more lines of code
c= 'c'; // initialized
// final lines of scripting
})();
开心时刻
如果我们现在返回到文章开头提到的问题,undefined
的代码部分:
var myvar = 'my value';
(function() {
alert(myvar); // undefined
var myvar = 'local value';
})();
我们会对myvar
为什么会alerting出undefined
有更好的理解了。正如我们所学到的,当局部变量myvar
声明后,它会自动被浏览器提升至函数作用域的顶部,在alert
的时候,变量早已经声明完成,然而,因为变量的初始化不会被提升的,所以变量的值是undefined
。
原文地址:JavaScript Hoisting Explained,作者: Jeffrey Way