JavaScript 变量提升和函数提升

JavaScript 变量提升和函数提升

作用域

在JavaScript中,一个变量的定义与调用都是会在一个固定的范围中的,这个范围我们称之为作用域。

作用域可以分为:

  • 全局作用域:如果变量定义在全局环境中,那么在任何位置都可以访问到这个变量。
  • 函数作用域:如果变量定义在函数内部,那么只能在函数内部访问到这个变量。
  • 块级作用域:如果变量定义在一个代码块中,那么只能在代码块中访问到这个变量。

块级作用域是在ES6中新增的,需要使用特定的let或者const关键字定义变量。

//全局作用域
var a = "global variable";

function fn() {
    //函数作用域
    var b = "function variable";
    console.log(a);
    console.log(b);
}

{
    //块级作用域
    let c = "block variable";
    console.log(c);
}

变量提升

全局作用域和块级作用域使用比较简单,但是函数作用域不一样,主要是因为在函数内部使用var定义的变量时,函数中会存在变量提升的问题。

通过var关键字定义的变量会发生变量提升,变量提升是将变量的声明提升到函数顶部的位置,而变量的赋值并不会被提升。

问题

//代码一
var a = "hello";
(function() {
    console.log(a); //hello
})();
//代码二
var a = "hello";
(function() {
    console.log(a); //undefined
    var a = "hello js";
})();

代码一正常输出,但是代码二输出“undefined”,这是因为发生了变量提升。

//代码二等价于:
var a = "hello";
(function() {
    var a; //变量提升
    console.log(a); 
    a = "hello js"; //赋值未提升
})();

函数提升

不仅通过var定义的变量会出现提升的情况,使用函数声明方式定义的函数也会出现提升。

函数提升会将整个函数体一起进行提升,包括里面的执行逻辑。

函数表达式,是不会进行函数提升的。

函数

fn();
function fn() {
    console.log("hello"); 
}
//上面代码等价于:
function fn() {
    console.log("hello"); 
}
fn();

函数表达式

fn(); //ncaught TypeError: fn is not a function
var fn = function() {
    console.log("hello");
}

同时使用函数和函数表达式

show(); //你好
var show;
function show() {
    console.log("你好");
}
show = function() {
    console.log("hello");
}

由于函数声明会被提升,因此最后输出的结果为“你好”。

函数提升覆盖

function fn() {
    function bar() {
        return 3;
    }

    return bar();

    function bar() {
        return 8;
    }
}
console.log(fn()); // 8

代码中使用函数声明定义了两个相同的bar()函数。由于变量提升的存在,两段代码都会被提升至foo()函数的顶部,而且后一个函数会覆盖前一个bar()函数,因此最后输出值为“8”。

变量提升和函数提升的优先级

同时存在变量提升和函数提升,但是变量提升的优先级要比函数提升的优先级高。

function fn() {
    console.log(typeof foo); // function
    // 变量提升
    var foo = 'variable';
    // 函数提升
    function foo() {
        return 'function';
    }
    console.log(typeof foo); // string
}
fn();
//上面代码等价于:
function fn() {
    var foo;
    function foo() {
        return 'function';
    }
    console.log(typeof foo); // function
    foo = 'variable';
    console.log(typeof foo); // string
}
fn();
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值