变量提升

266 阅读2分钟

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

前言

ECMAScript 6.0 简称ES6 , 是 JavaScript 语言的新一代的标准,于在 2015 年 6 月发布,正式名称就是《ECMAScript 2015 标准》。一般情况,泛指, 5.1版以后的标准,涵盖了 ES2015、ES2016、ES2017、ES2018、ES2019、ES2020、ES2021 等等

今天我们一起来学习变量提升吧。

变量提升是什么

函数声明和变量声明总是被JavaScript解释器隐式地提升(hoist)到包含他们的作用域的最顶端。

function log(){
    console.log("name:", name);
    var name = "tom";
    console.log("name:", name);
}
log();
// name: undefined
// name: tom

其等同于下面的代码:

function log(){
    var name;
    console.log("name:", name);
    name = "tom";
    console.log("name:", name);
}

第一个console.log时,其已被申明,但是没有赋值, 第二个console.log的时候,已经赋值。

函数申明 VS 变量申明和赋值

如果普通 变量申明和赋值 遭遇 函数申明,你觉得会怎样呢?

function log(){    
    console.log("name1:", name);
    var name = "tom";
    function name(){
        console.log("name fun:", nmae);
    }
    console.log("name2:", name);
}
log();

截图_20212002092016.png
当然是函数申明胜出,函数表达式其实就是普通的变量申明了。

函数申明 VS 变量申明和赋值 VS 形参

如果再遭遇函数形参呢?

function log(name){    
    console.log("name1:", name);
    var name = "tom";
    function name(){
        console.log("name fun:", nmae);
    }
    console.log("name2:", name);
}
log("flower");

截图_20212602092643.png

结局: 函数申明 > 变量申明 > 形参

不带关键字的变量申明

大家都知道,不带关键的变量申请,会挂载到全局对象上,我们看看其是否能够变量提升。

num1 = 10;
console.log("num1:", num1);  // 10
console.log("num1:", num1);
num1 = 10; 
// VM521:1 Uncaught ReferenceError: num1 is not defined

可以看到不带var关键的变量申明, 不会变量提升。代码执行到的时候,先查询作用域链,如果未被定义,才会在全局对象上添加对象的属性和值。

let和const不存在变量提升

console.log("num1:", num1);
let num1 = 10; 
// Uncaught ReferenceError: num1 is not defined
console.log("num1:", num1);
const num1 = 10; 
// Uncaught ReferenceError: num1 is not defined

小测试

var num = 1;
function log() {
    if (true) {
        var num = 10;
    }
    console.log(num);  
}
log()
console.log(num);

答案输出是 10, 1

var num = 1;
function log() {
    if (true) {
        num = 10;
    }
    return;
    function num(){}
}
log()
console.log(num);

答案是 1

function arg(){
    var arguments;
    console.log(arguments);
}

arg(1,2,3);  

答案: Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]

function arg(arguments){
    var arguments;
    console.log(arguments);
}

arg(1,2,3);  

答案: 1

小结

今天你收获了吗?

引用

[翻译]JavaScript Scoping and Hoisting