变量提升(hositing),顾名思义就是将最下面的东西提升到上面了,将js中下面定义的东西(变量或者函数),提升到前面来定义; 理解提升之前,先了解一下js的作用域(scoping):
在java、C、C++等语言中,变量有块级作用域(block-level scope)的概念,也就是说某个变量只会在一个作用域块中可用(或者是值可用)
例如C程序的代码:
#include <stdio.h>
int main() {
intx = 1;
printf("%d,", x); // 1
if(1) {
intx = 2;
printf("%d,", x); // 2
}
printf("%d\n",x); // 1
}
输出:1,2,1 时因为if判断中的x只会在if那个作用域块中生效,这些变量不会影响到外部作用域;
但是js中却不是这样,代码如下:
var a =1;
console.log(a);
if(a){
var a=2;
console.log(a);
}
console.log(a);
输出的是1,2,2;很明显,在js中,if块中的a变量并不是只在if块中有效,也就是说它没有创建一个新的作用域;在js中,只有函数才会创建新的作用域,如下代码:
var a=1;
console.log(a);
if(a){
(function(){
var a=2;
console.log(a)
}())
}
console.log(a)
输出 :1,2,1
这种方法非常灵活,可以使用在任何需要创建临时作用域的地方;js的这种作用域Scoping非常强大,理解了它会与理解hositing会更容易
1、变量提升,只是把变量的声明提升到函数的顶部,而不会把赋值也提升上来。例如代码:
function(){
var a=1;
var b=2;
var c=3;
}
实际上是这样的:
function(){
vara,b,c;
a=1;
b=2;
c=3;
}
这个时候就是变量提升了。
下面看一个面试中遇到的笔试题:
var a=1;
(function(){
alert(a);
var a=2;
}())
这个地方会弹出 "undefined",结合上面的变量提升以及js的作用域Scoping,就可以很好的理解,实际上这段代码是这样的:
var a =1;
(function(){
var a;
alert(a);
var a=2;
}())
所以会弹出undefined
2、函数提升,与变量提升类似,函数提升是把整个函数提到前面去;在此之前,先了解js中声明函数的两种方式:
a、函数声明式 function test(){}
b、函数表达式 var test = function(){}
而这里我们提到的函数提升只针对以函数声明形式创建的函数才能被提升。
我们在写代码的时候经常与碰到这样的问题:通过函数声明式写的代码,可以在该函数的上面直接调用:
test();
function test(){
alert("test")
}
这个地方会弹出"test"
而通过函数声明式写的代码,不能在该函数的上面直接调用:
test();
var test=function(){}
会提示错误
这里就可以看出,在js中的函数提升只能针对用声明式定义的函数
注意:同时使用声明式方式定义函数,和表达式方式声明函数,最后总是使用表达式方式定义的函数,因为声明式方式定义的函数被提升到最上面,后面表达式方式定义的函数就会覆盖掉它:
var f = function() {
console.log('1');
}
function f() {
console.log('2');
}
f()
输出:1
function f() {
console.log('2');
}
var f = function() {
console.log('1');
}
f()
输出:1