什么是变量提升呢?
正如字面意思,就是把定义在后面的变量或函数,提升到前面来使用。
变量提升,简单来说,就是把定义的变量提升到一块作用域当中(或者说一个函数)顶端的位置,需要注意的是,变量提升,只是提示变量的声明,并不会将变量的赋值一同提升上来。
比如下面代码1
2
3
4
5(function(){
var a = 1;
var b = 2;
var c = 3;
})()
我们在函数中定义了3个变量,而实际上,相当于这种写法1
2
3
4
5
6(function(){
var a,b,c;
a = 1;
b = 2;
c = 3;
})()
函数声明提升
函数创建有两种方法
函数声明语法:1
2
3
4f('hello world!');
function f(name) {
console.log(name);
}
运行上面的程序,控制台能打印出hello world!
函数表达式语法:1
2
3
4f('hello world!');
var f = function(name) {
console.log(name);
}
运行上面的代码,会报错Uncaught ReferenceError: f is not defined(…)错误信息,显示f没有被定义。
因为,函数声明有一个非常重要的特征:函数声明提升,函数声明语句将会被提升到外部脚本或者外部函数作用域的顶部。正是因为这个特征,所以可以把函数声明刚在调用它的语句后面。1
2
3
4
5
6
7var getName = function(){
console.log(2);
}
function getName(){
console.log(1);
}
getName();
正如前面所说到的函数声明提升,函数声明function getName(){}的声明会被提前到顶部,而函数表达式var getName = function(){}则表现出变量提升。因此在这种情况下,getName也是一个变量,因此这个变量的声明也将提升到顶部,而变量的赋值依然保留在原来的位置。
相当于1
2
3
4
5
6
7
8var getName;
function getName(){
console.log(1);
}
getName = function(){
console.log(2);
}
getName(); //最终输出2
在原来的例子中,函数声明虽然是在函数表达式后面,但由于函数声明提升到顶部,因此后面getName又被函数表达式的赋值操作给覆盖了,所以输出2.
特别说明:函数提升会先于变量提升,看下面这个例子1
2
3console.log(typeof name)//输出function
var name = "123";
function name(){}
下面一题来测测你是否完全理解1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function Foo(){
getName = function(){ alert(1) };
return this;
}
Foo.getName = function(){ alert(2) };
Foo.prototype.getName = function(){ alert(3) };
var getName = function(){ alert(4) };
function getName(){ alert(5) };
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
答案1
2
3
4
5
6
7Foo.getName(); //2
getName(); //4
Foo().getName(); //1
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName(); //3