概述:
JavaScript
在运行某个作用域中的代码前,会将变量声明(前)和函数声明(后)提升到当前作用域的顶部。
[注1]:这种提升一般发生在创建每个作用域的上下文对象时。即提升是相对于作用域而言的。
[注2]:变量提升放在函数提升前面。
[注3]:匿名变量和函数不会被提升。
[注4]:匿名变量在运行时遇到会被隐式声明为全局变量。
一、变量提升
以一段JavaScript
代码为例:
function foo() {
console.log(a);
a = 1;
console.log(a);
var a;
}
foo();
输出结果是多少呢?我们按照变量提升的规则分析一下这段代码,将变量声明提升到这个函数作用域的顶部:
function foo() {
var a;
console.log(a);
a = 1;
console.log(a);
}
foo();
结果也确实和提升后的运行结果一致。第一个输出a=undefined
,第二个输出a=1
。
二、函数提升
函数的提升和变量提升类似,将函数声明移到顶部,且放在变量声明后面,同样以一段代码为例,观察一下函数声明提升是不是在变量声明提升的后面:
function foo() {
console.log(a);
var a;
function a () {};
}
foo();
function foo() {
console.log(a);
function a () {};
var a;
}
foo();
这两段代码的运行结果都是ƒ a () {}
,说明第二段代码的函数声明提升后放在变量提升的后面,覆盖了变量a
的默认值undefined
。
这两段代码提升后的代码一致,都是:
function foo() {
var a;
function a () {};
console.log(a);
}
foo();
三、隐式变量
看两段代码:
function foo() {
a = "aaa";
console.log(a);
}
foo();
console.log(a);
function foo() {
a = "aaa";
console.log(a);
var a = "bbb";
}
foo();
console.log(a);
它们分别输出什么?
对于第一段代码,经过声明提升后,变成:
function foo() {
a = "aaa";
console.log(a);
}
foo();
console.log(a);
是的,并没有什么变化。因为在函数foo
作用域下没有显式的变量和函数声明,也就没有声明提升。
于是函数直接执行,遇到第一句a = "aaa";
,由于在作用域中找不到这个变量,所以js引擎直接在全局声明了一个变量a
(非严格模式下),相当于:
var a;
function foo() {
a = "aaa";
console.log(a);
}
foo();
console.log(a);
这样就很好理解了,下面两个输出都是aaa
,因为变量a
是全局变量。
我们再来分析一下第二段代码,声明提升后:
function foo() {
var a;
a = "aaa";
console.log(a);
a = "bbb";
}
foo();
console.log(a);
注意:这个函数里面,变量a
是局部变量,a = "aaa";
仅仅是对局部变量a
的赋值,不会有创建一个全局变量a
的举动。
所以第一个console.log
输出了aaa
,第二个则会报错:Uncaught ReferenceError: a is not defined
,表示当前作用域找不到需要打印的变量a
。
网友评论