我们知道,JS执行时机不同,得到的结果也会不同,这里会以一些简单的例子来做一次整理总结
案例
例1
let a = 1
function fn(){
console.log(a)
}
这里会打印出什么?
什么也不会打印,因为并没有调用函数
例2
let a = 1
function fn(){
console.log(a)
}
fn()
这里会打印出什么?
很简单,1,我们在声明了a之后,执行了函数
例3
let a = 1
function fn(){
console.log(a)
}
a = 2
fn()
这里会打印出什么?
2,因为在执行fn()之前,a被从新赋值为2
例4
let a = 1
function fn(){
console.log(a)
}
fn()
a = 2
这里会打印出什么?
1,因为在执行fn()之后,a才被从新赋值
在作用域中JS函数的执行时机
例5
function f1(){
let a = 1
function f2(){
let a = 2
function f3(){
console.log(a)
}
a = 22
f3()
}
console.log(a)
a = 100
f2()
}
f1()
这里会打印出什么?
1,22
因为在f3()中并没有变量a,所以它会向上取最近的作用域f2()中的a,这里的a值为2
但是我们在执行f3()之前,又给a重新赋值了一个新值:22,所以执行f3()打印出的a值为22
而在最外层的f1()中,a的值为1,在下方是先执行console.log(a)
之后才重新声明a = 100
,所以在这里打印a,值只会是1。
setTimeout
例6
let a = 1
function fn(){
setTimeout(()=>{
console.log(a)
},0)
}
fn()
a = 2
这里会打印出什么?
2,setTimeout会先执行完当前代码,再执行自身,也就是说,在let a = 1,fn(),a=2都执行完之后,才会执行console.log(a)
例7
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
这里会打印出什么?
6个6,同上,setTimeout会先执行完for循环,再打印出i的值,而执行完循环之后,i的值已经变成了6,且这样的循环执行了6次,所以打印出6个6
怎么理解setTimeout?
两个字理解:马上
何为“马上”?
简单的举例,当你正在进行一把激情四射的LOL时,你的母亲大人突然打开你的房门喊你吃饭,你会跟她说“马上就来”。
那么你的“马上”的含义是:
- 放下游戏,立刻去吃饭
- 打完这一局游戏,再去吃饭
不用想,答案肯定是2,
所以setTimeout同理,当你让它执行console.log(i)
时,它会告诉你“马上执行”,这个“马上”就是等它执行完for循环之后,才会执行console.log(i)
那么应该怎么用for+setTimeout打印出0,1,2,3,4,5呢?
方法1
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
ES6,引入的新方法,它在每一次循环中,拷贝一个i,把拷贝的i留在setTimeout里,第一次循环把i=0留在里面,第二次留1,以此类推,每次循环生成一个新的i(但其实这么一来,setTimeout也就没有意义了),
可以用如下代码理解:
let i = 0
setTimeout(()=>{
console.log(i)
},0)
let i = 1
setTimeout(()=>{
console.log(i)
},0)
以此类推
方法2
for( var i = 1 ; i < 6 ; i++ ){
(function(j){
setTimeout( function(){
console.log( j )
},0)
})(i)
}
运用立即执行函数,闭包