每天一个小技巧js篇-变量和函数提升

643 阅读2分钟

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 是函数表达式。具名函数中,可以在函数内部改变函数名 而函数表达式,如果有函数名,则它的函数名只能作用在其自身作用域中,且不可改变函数名称。