var function的变量提升(无条件)
打开一个标签页浏览器就会分配一块内存作为全局执行上下文栈(ECStack) 全局执行上下文(EC(G))压入栈内,随后全局的作用域下词法解析,变量提升=>代码自上而下依次解析遇到var就要变量提前声明,遇到function就要提前声明并赋值
var function的变量提升(条件内)
老版浏览器 无论function是否在条件内,变量提升都是声明并定义
新版浏览器 function和var定义在条件代码块中,var还是会在块的外部只声明,但function也是只声明不会定义,在块的内部如果有let const function就会产生块级作用域,在这里的function会变量提升,并且代码在执行到function时会把块级作用域前面的改变映射到上级作用域
例子
var a=0
if(true){
a=1
function a(){}
a=21
console.log(a)
}
console.log(a)
在老版浏览器(ie10及以下)
首先浏览器从内存中条中开辟一块栈内存(ECStack),将一个全局执行上下文压入栈内,开辟一块堆内存,存储GO对象,window指向GO对象,在压入的全局作用域中词法解析(一般像let的重复声明就会报错),变量提升

在新版浏览器下
如果function的声明在条件内(不论条件是否成立function都只声明,并且像if或for这种块存在let/function/const就会产生块级作用域)
变量提升:var a //这里的function在条件语句中只声明
a=0
块级作用域start
变量提升: function a(){}
a=1 //function之上映射到全局
function a(){} =>不执行
a=21
console.log(a) =>21
块级作用域end
cosole.log(a) =>1
在块级作用域中不能重复声明变量
if(true){
function a(){}
var a=0
}
//报错
总结
新版浏览器中存在块级作用域=>块中使用了let/const/function就会形成块级作用域, 因为既要兼容es3 es5 又要兼顾es6所以在块中的var 和function都会在全局声明,但并不定义,在全集会变量提升块中用var 和 function定义的变量(function不赋值),在块级作用域中function变量提升并赋值,执行function之前的代码要映射到全局(function在全局声明过,与全局有关-为了兼顾es3),映射到全局的内容包含块级作用域的变量提升