什么是变量提升:当栈内存(作用域形成),JS代码自上而下执行之前,浏览器首先会把所带 var / function 关键字的进行提前声明 或者 定义 ( 这个过程也可以叫预编译 ),预编译阶段也有几点注意事项,咱们来看一看。
在变量提升阶段:
1.带 VAR 的只声明未定义,而带 FUNCTION 的声明和定义都完成了
![3daa41c82437fc25288e858b635850dc.png](https://img-blog.csdnimg.cn/img_convert/3daa41c82437fc25288e858b635850dc.png)
在全局作用域下声明就相当于是给 window 对象添加了属性,属性名能重复嘛?答案肯定是不可以的,还有网上有很多资料说函数的优先级大于变量的优先级,我个人感觉这种说法不合理,大家一起来看一道题:
![915ae31dc31d975471b34b393ef76e56.png](https://img-blog.csdnimg.cn/img_convert/915ae31dc31d975471b34b393ef76e56.png)
那从上面可以看出,根本就没有什么优先级,只有提升不断重新赋值而已。
2.变量提升只发生在当前作用域下(例如:开始加载页面的时候只对全局作用域下的进行提升,因为此时函数中存储的都是字符串而已)
![b6c264ea1b1a5d6d6527dd929d649b61.png](https://img-blog.csdnimg.cn/img_convert/b6c264ea1b1a5d6d6527dd929d649b61.png)
3.变量提升只对等号左边的值进行处理,例如:
![c8e834111e48b0d2fafe2a247b655bb9.png](https://img-blog.csdnimg.cn/img_convert/c8e834111e48b0d2fafe2a247b655bb9.png)
4. 带 function的 在老版本浏览器渲染机制下,声明和定义都会处理,但是为了迎合ES6中的块级作用域,新版浏览器对于函数(在条件判断中的函数),不管条件是否成立,都只是先声明,没有定义,类似于 var,但是在 条件成立的情况下第一件事并不是代码执行,而是类似于变量提升一样,先把fn 声明和定义了
![a2667330130934402cd013b6ad295675.png](https://img-blog.csdnimg.cn/img_convert/a2667330130934402cd013b6ad295675.png)
5.带关键字 VAR 和 不带关键字 VAR 的区别:
![46dde32b518f6b2c99325eafc5c23c0e.png](https://img-blog.csdnimg.cn/img_convert/46dde32b518f6b2c99325eafc5c23c0e.png)
var 声明一个变量其实可以说是给 window 全局对象设置了一个属性,变量的值就是属性值,私有作用域中声明的私有变量和 window 无关,全局变量和 window 中的属性存在 “ 映射机制 ”,从赋值可以看出,window.a 改变了变量 a 的值。
不使用 var 的话 可以理解为给 window 对象 添加了一个属性,没有提升,此时作用域链中没有这个 b 所以就会报错。
以上就是本人对 var 变量提升的理解及认知,面试的时候也有会不少公司问到,其实就一句,不想有变量提升 可以使用ES6中 let ,但是变量提升你还不能不掌握 ,在这里就不说 let 了,最后给大家来一道面试题开开胃,下方附图片及代码
![427fc2c1dd17846c24dea380df980e9d.png](https://img-blog.csdnimg.cn/img_convert/427fc2c1dd17846c24dea380df980e9d.png)
f = function () { return true; }
g = function () { return false; }
~function () {
if (g() && [] == ![]) {
f = function () { return false; }
function g() { return true; }
}
}();
console.log(f()); console.log(g());
这道题只适用于新版浏览器,不要怀疑题目给错了,各位看看考点在那里吧
还有那句话:如有不对之处及不周之处请大佬们指出,也希望对一些人有所帮助,咱们下次再会!