共计 1690 个字符,预计需要花费 5 分钟才能阅读完成。
前言
欢送关注『前端进阶圈』公众号,一起摸索学习前端技术 ……
前端小菜鸡一枚,分享的文章纯属个人见解,若有不正确或可待探讨点可随便评论,与各位同学一起学习~
JavaScript 为什么要进行变量晋升,它导致了什么问题?
- 无论是函数还是变量在那个地位上申明,都会被晋升到函数之前,可保障变量申明前可拜访而不会报错
- 变量晋升的实质:js 引擎在代码执行前有一个解析的过程,会创立一个执行上下文,初始化一些代码执行所须要的参数。当拜访一个变量时,会在以后执行上下文的作用域链中去查找,而作用域链的首端指向的是以后执行上下文的变量对象,这个变量对象是执行上下文的一个属性,它蕴含了函数的形参,所有函数和变量申明,这个对象是在代码解析的时候创立的。
代码执行过程:
-
解析阶段:JS 会查看语法,并对函数进行预编译。解析的时候会先创立一个全局执行上下文环境,先把代码中行将执行的变量、函数申明都拿进去,变量先赋值为 undefined,函数先申明好可应用。在一个函数执行之前,也会创立一个函数执行上下文环境,跟全局执行上下文相似,不过函数执行上下文会多出 this、arguments 和函数的参数。
- 全局上下文:变量定义,函数申明
- 函数上下文:变量定义,函数申明,this,arguments
- 执行阶段:依照代码程序执行
为什么要进行变量晋升?
- 进步性能:在代码执行前,会进行语法检查和预编译,这个操作只会执行一次,这么做就是为了进步性能,如果没有这一步,则每次执行代码前都必须从新编译一下变量和函数,这是没有必要的,因为变量和函数的代码根本不会扭转,解析一遍就够了。
-
容错性更好
a = 1; var a; console.log(a); // 1
S(总结):
- 解析和预编译过程中的申明晋升能够进步性能,让函数能够在执行时事后为变量调配栈空间
- 申明晋升还能够进步 JS 代码的容错性,使一些不标准的代码也能够失常执行
导致的问题:
var tmp = new Date();
function fn(){console.log(tmp);
if(false){var tmp = 'hello world';}
}
fn(); // undefined
/**
* 在这个函数中,本来是要打印出外层的 tmp 变量,然而因为变量晋升的问题,* 内层定义的 tmp 被提到函数外部的最顶部,相当于笼罩了外层的 tmp,所以打印后果为 undefined。*/
for (var i = 0; i < 3; i++){setTimeout(() => {console.log(i);
}, 2000);
} // 3 3 3
for (let i = 0; i < 3; i++){setTimeout(() => {console.log(i);
}, 2000);
} // 0 1 2
/**
* 因为遍历时定义的 i 会变量晋升成为一个全局变量,在函数完结之后不会被销毁,* 所以,始终批改的是之前的定义的全局变量,所以第一个输入三次 3, 第二个输入 0 1 2。*/
/**
* 在 for 循环中,let 申明的变量会存在一个块级作用域的概念,应用 let 申明的迭代变量时,* js 引擎会在后盾为每一个迭代循环申明一个新的迭代变量,因而每次应用的 i 都是不同的。*/
文章特殊字符形容:
- 问题标注
Q:(question)
- 答案标注
R:(result)
- 注意事项规范:
A:(attention matters)
- 详情形容标注:
D:(detail info)
- 总结标注:
S:(summary)
- 剖析标注:
Ana:(analysis)
- 提醒标注:
T:(tips)
往期回顾:
- 热点面试题:浏览器和 Node 的宏工作和微工作?
- 这是你了解的 CSS 选择器权重吗?
- 热点面试题:JS 中 call, apply, bind 概念、用法、区别及实现?
- 热点面试题:罕用位运算办法?
- Vue 数据监听 Object.definedProperty() 办法的实现
- 热点面试题:Virtual DOM 相干问题?
- 热点面试题:Array 中有哪些非破坏性办法?
-
热点面试题:协商缓存和强缓存的了解及区别?
最初:
- 欢送关注『前端进阶圈』公众号,一起摸索学习前端技术 ……
- 公众号回复 加群 或 扫码, 即可退出前端交流学习群,长期交流学习 ……
- 公众号回复 加好友,即可添加为好友
正文完