JS基础 —— 变量提升

测试环境 chrome 79.0.3945.79 (正式版本) (64 位) (cohort: Stable)

“变量提升”并不是说变量和函数的声明会在物理层面移动到代码的最前面!实际上,变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中!

变量提升 & 函数提升

先看下面两段代码

foo();
var foo = function(){
    console.log('变量');
}
foo();
function foo(){
    console.log('函数');
}
foo();

// 输出
函数
变量
变量

预编译后
// 函数声明提升优先级比变量声明高,也就是说,函数声明提升比较靠前
function foo(){
    console.log('函数');
}
var foo; // 由于未初始化,所以不覆盖上面的

foo(); // 此时foo还是函数 --> 函数
foo = function(){
    console.log('变量');
}
foo(); // foo被变量覆盖了 --> 变量
foo(); // 无变化 --> 变量

foo();
function foo(){
    console.log('函数');
}
foo();
var foo = function(){
    console.log('变量');
}
foo();

// 输出
函数
函数
变量

预编译后
function foo(){
    console.log('函数');
}
var foo;

foo();
foo();
foo = function(){
    console.log('变量');
}
foo();

参考MDN

猜测:预编译的时候,函数声明和变量声明都会提升(提升后的相对位置,在下面大胆猜测一下),变量未初始化会被忽略,变量初始化后会覆盖同名变量和函数。

  • 猜测1:变量声明和函数声明按照相对位置(script中定义的位置)提升,但是变量提升时总是未初始化的,所以遇到同名变量,直接忽略,知道运行到变量初始化的位置,前边同名的值会被覆盖

  • 猜测2:变量声明总是在函数声明前,或总是在其后(可以分别保存在堆的两块空间里)

    • 变量声明在函数声明前,则一致采用覆盖原则
    • 变量声明在函数声明后,则遇到未初始化的时候采取忽略原则,否则覆盖

实践如下↓

var声明的变量和function声明的函数同名的情况

// 变量
var a; // 声明
var a = num; // 声明 + 初始化

// 函数
function fun(){}; // 声明
  1. var声明的变量同名:取后声明的,如果后声明的已经初始化了(包括undefined值)。

  2. function声明的函数同名:取后声明的。

  3. var变量和function函数同名:取变量,如果变量已经初始化了(包括undefined值);否则取函数。

let和const不能重复声明变量

报错:Uncaught SyntaxError: Identifier 'num' has already been declared
posted on 2019-12-18 14:41  亭早  阅读(166)  评论(0)    收藏  举报