if 创建的块级作用域中,var 可以提升作用域至外面

function testScope() {

var funInner = "Inner";
funcOut = "outer"; //没有 var 声明,会被自动提升到 全局作用域

if (true) {
var ifInner = "Inner if true"; //变量的作用域被自动提升到 testScope fun
ifOuter = "Outer if true"; //没有 var 声明,会被自动提升到 全局作用域
}

if (false) {
var ifInnerFalse = "Inner if false";//变量的作用域被自动提升到 testScope fun
ifOuterFalse = "Outer if false"; //可以防止变量的作用域被自动提升
}

console.log(funInner); //Inner
console.log(funcOut); //outer
console.log(window.funcOut); //outer
console.log(ifInner); //Inner if true
console.log(ifInnerFalse); //undefined
console.log(ifOuter); //Outer if true
console.log(window.ifOuter); //Outer if true
console.log(ifOuterFalse);//ReferenceError: ifOuterFalse is not defined
}
testScope();

/* typeof 可以用来补全一些全局方法或变量 */
//console.log(globalFun);//ReferenceError: globalFun is not defined
console.log(typeof globalFun);// "undefined"
if (typeof globalFun === "undefined") {
globalFun = function () { //不使用 var ,如果变量已经存在,将不会被重复声明,可以防止某些变量重名而出错
console.log("this is my global function;");
}
}

经常看到有文章说: 用 let 和 const 申明的变量不会提升。其实这种说法是不准确的,比如下面代码:

var x=1;
if(true){
console.log(x);
let x=2;
}

上述代码会报错 Uncaught ReferenceError: Cannot access ‘x’ before initialization。如果 let 申明的 x 没有变量提升,那我们在他前面 console 应该拿到外层 var 定义的 x 才对。但是现在却报错了,说明执行器在 if 这个块里面其实是提前知道了下面有一个 let 申明的 x 的,所以说变量完全不提升是不准确的。只是提升后的行为跟 var 不一样,var 是读到一个 undefined,而块级作用域的提升行为是会制造一个暂时性死区(temporal dead zone, TDZ)。暂时性死区的现象就是在块级顶部到变量正式申明这块区域去访问这个变量的话,直接报错,这个是 ES6 规范规定的。