变量提升 的问题竟然只有你一个

2020.09.20
评论

变量提升

var定义的内容会导致变量提升(同一作用域内,无论使用var定义在哪里的内容,都会在最前面提前声明,在原定义的地方赋值,且变量提升不会受if影响,这是在预编译时发生的时,和执行时无关),如果在全局中使用var,则会被设置在window上;函数同样存在变量提升,且优先级大于var定义的同名内容(函数>arguments>var变量)

var name = 'erdong';
(function () {
    if (typeof name === 'undefined') {  // 此时name为undefined
        var name = 'chen'; // 变量提升,在自执行函数最前面声明了name
        console.log(name); // 执行输出
    } else {
        console.log(name);
    }
})();
var a = 10;  
function test() {  
    a = 100;  // 变量提升,所以赋值test方法内声明的a
    console.log(a); // 输出test中的a
    console.log(this.a);  // 输出test执行地方的a
    var a;  // 新定义a变量,变量提升
    console.log(a); // 输出test中的a
}
test();  
if (!('a' in window)) {
    var a = 1; // 变量提升,到全局作用域window;var声明在全局上会被声明到window上
}
console.log(a); // 输出undefined 
var c = 1; // 覆盖c方法
function c(c) { //变量提升到最前面
    console.log(c);
    var c = 3;
}
console.log(c); //输出1
c(2); // 报错 c is not a function
console.log(c); // c方法
var c; // 变量提升,移动到最前面声明
function c(a) {
    console.log(a); // 输出a方法
    var a = 3; // 定义了新变量a,变量提升到方法c的最前面声明
    function a(){ // 变量提升优先于变量a
    }
}
c(2); // 输出a方法
(function() {
  var a = b = 3; // a在自执行函数内声明,b未声明,所以变量提升到全局作用域
})();
console.log(typeof a === 'undefined'); // a为函数私有,所以使用会报错,typeof对报错内容执行会返回undefined,所以输出true
console.log(typeof b === 'undefined'); // b为全局内容,在函数内被赋值为3,所以输出false
console.log(typeof a); // 输出function
function a() {} // 变量提升
var a; // 已存在a,无操作
console.log(typeof a); // 输出function
var x = 1;
if(function f(){}){ // 判断条件会被转Boolean类型,不存在变量提升
    x += typeof f;
}
console.log(x); // 输出1undefined

总结

  1. 变量提升属于预编译范畴,只要使用var定义了,在同一作用域(全局或函数作用域)内就会被提示(如没有执行到的if内部,如果其内部存在var,则仍会被提示)
  2. 变量提升存在先后顺序,function>agruments>var,优先级以及定义位置越靠前,则提升
  3. function和var提升的差别在于,function是整体提升(名称以及函数自身,相当于提升加赋值),var只是定义提升(提升后值为undefined,在原本定义处再进行赋值)
  4. 对于未定义过的变量赋值,会将其在外层作用域进行变量提升