1.变量提升
首先,先丢出来一道题:
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
如果我们不了解 javascript 中的变量提升和函数声明提升,那么我们的答案肯定是 1。
那么正确的答案是什么呢? 我们首先把这段代码还原:
var foo = 1;
function bar(){
var foo;
if(!foo){
foo = 10;
}
alert(foo);
}
bar();
好了,这下看一看执行结果是什么呢?
// 输出 10
为什么会发生提升?
首先我们需要知道一点编译原理的知识。JavaScript 的源代码在运行的时候,会经过两个阶段:编译和执行。而且,编译阶段往往就在执行阶段的前几微秒甚至更短的时间内。
具体可以自行查阅相关资料
2.函数提升
函数提升和变量提升还有点不一样。函数提升,只会提升函数声明,而不会提升函数表达式。
例如:
f();
fn();
// 函数表达式
var fn = function(){
console.log(1);
}
// 函数声明
function f(){
console.log(0);
}
这里我们把代码还原,我们来看一下:
// 函数声明
function f(){
console.log(0)
}
var fn;
f();
fn();
fn = function(){
console.log(1);
}
这下明白为什么执行函数 fn 的时候,会报错了吧。
3.实战
现在,大家是不是对变量和函数声明的提升机制已经有一定的了解了?那么让我们在深度实战一下。
console.log(a);
console.log(typeof f);
var flag = true;
if(!flag){
var a = 1;
}
if(flag){
function f(a){
f = a;
console.log(1);
}
}
if(flag){
function f(){
console.log(2);
}
}
function f1(){
function f(){
console.log(3);
}
}
console.log(typeof f);
f1();
f();
在非严格模式下,代码块中,只有使用 var 声明的变量和函数声明是可以提升的,但是函数声明只能将函数的名字提升出去。
输出结果为:
undefined
undefined
function
2
- 解释:在非函数作用域中,函数声明是可以提升的,例如:
if(flag){
function f(){
console.log(2);
}
}
其中 f() 是可以提升的,所以执行会输出 2
最后再来看一个题
function f1(){
console.log(typeof f1);// function
f1 = 3;
console.log(typeof f1);//number
}
f();
var f2 = function f2(){
console.log(typeof f2);//function
f2 = 3;
console.log(typeof f2);//function
}
f2();
上述代码中,函数 f1 是具名函数,函数 f2 是函数表达式。具名函数中,可以在函数内部改变函数名 而函数表达式,如果有函数名,则它的函数名只能作用在其自身作用域中,且不可改变函数名称。