(1)let 和const
console.log(val);//变量声明提升到前面,但赋值不会提升,故为Undefined
if(true){
var val = 12;
}
//等价于
var val;
console.log(val);
if(true){
var val = 12;
}
console.log(val);//不提升,报错Error
if(true){
let val = 12;
}
if(true){
const val = {};
val.name = "liming"
}
console.log(val);//访问不到,报错Error
(2)微任务和宏任务
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval
- micro-task(微任务):Promise,process.nextTick
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
}).then(function() {
console.log('then');
})
console.log('console');
- 这段代码作为宏任务,进入主线程。
- 先遇到
setTimeout
,那么在Event Table注册回调函数,注册后分发到宏任务Event Queue。 - 接下来遇到了
Promise
,new Promise
立即执行,then()的回调函数在Event Table里注册,注册完了后
分发到微任务Event Queue。 - 遇到
console.log()
,立即执行。 - 好啦,整体代码script作为第一个宏任务执行结束。看有哪些微任务?我们发现了
then()的回调函数
在微任务Event Queue里面,执行。 - ok,第一轮事件循环结束了。我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务Event Queue中
setTimeout
对应的回调函数,立即执行。 - 结束。
- 打印顺序是:promise console then setTimeout
原著链接在此:https://juejin.im/post/59e85eebf265da430d571f89
遇到面试怎么答?
事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
(这个回答还是欠缺呀:按照这个答:从整体代码出发,遇到宏任务,执行宏任务,在Event table 注册宏任务回调函数,注册完了后把宏任务回调函数放到宏任务事件队列里;遇到微任务,执行微任务,在Event table 注册微任务回调函数,注册完了后把微任务回调函数放到微任务事件队列里。一趟执行下来之后,再去执行所有的微任务事件队列。然后再从宏任务出发,找宏任务事件队列去执行,执行完了后再执行所有的微任务)
js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。
(3)@keyframes规则 实现一个动画:从完全不透明到完全透明,5s(理论上是这样,但是在w3school里没效果)
<!DOCTYPE HTML>
<html>
<head>
<style>
div {
width:100px;
height:100px;
background:red;
animation:myFirst 5s;
}
@keyframes myFirst{
0% {opacity:0}
100% {opacity:100%}
}
//或者是下面样式
@keyframes myFirst{
from {opacity:0}
to {opacity:100%}
}
</style>
</head>
<body>
<div></div>
</body>
</html>