时机不同,结果不同。
举例说明:
例一:
let a = 1
function fn(){
console.log(a)
}
这里不会打印出任何东西,因为函数只是进行了声明,但是没有被调用。
例二:
let a = 1
function fn(){
console.log(a)
}
fn() // 1
会打印出 1,这里是对例一进行完善
上述代码表示:
- 声明变量
a并赋值为1 - 声明一个函数
fn,内容是打印出a - 调用函数
fn - a 是 1 ,所以打印出
1
例三:
let a = 1
function fn(){
console.log(a)
}
a = 2
fn() // 2
结果打印出 2
上述代码表示:
- 声明变量
a并赋值为1 - 声明一个函数
fn,内容是打印出a a赋值为2- 调用函数
fn - 在调用函数
fn时,a 已经被赋值为 2 ,所以在调用函数fn时, a 是 2
例四:
let a = 1
function fn(){
console.log(a)
}
fn()
a = 2
结果打印出 1
上述代码表示:
- 声明变量
a并赋值为1 - 声明一个函数
fn,内容是打印出a - 调用函数
fn a赋值为2- 这里在调用函数
fn时,a 的值还是 1 ,被调用后再赋值的2 。所以在调用函数fn时, a 是 1
例五:
let a = 1
function fn(){
setTimeout(()=>{
console.log(a)
},0)
}
fn()
a = 2
结果打印出 2
上述代码表示:
- 声明变量
a并赋值为1 - 声明一个函数
fn,内容是当前代码执行完毕后,再打印出a - 调用函数
fn a赋值为2- 因为
setTimeout表示等到当前代码执行完毕后,再执行。所以调用函数fn时并没有立即执行console.log(a)(如果没有setTimeout而立即执行的话,此时 a 是 1 ,fn()调用打印出也是1;同例四)。而等到执行的时候 a 已经变成 2 了,此时打印会打印出2
关于setTimeout
setTimeout表示尽快执行,不是立即执行。可以理解为等到当前代码执行完毕后,再执行。
通俗的举例来说:比如我正在打游戏,这时候妈妈让我去吃饭,我嘴上说马上,但其实会把游戏打完之后再立马跑去吃饭。
特殊情况
例一:
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
结果会打印出 6 个 6
理由:setTimeout表示尽快执行,即会等到当前代码的for循环执行完了,再去执行console.log(i)。而for循环执行完之后,i已经是6了,所以会打印出6个6 。
例二:
如果将let i = 0放到for循环里面,打印结果会有不同
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
结果会打印出 0、1、2、3、4、5
理由:JS 在 for 和 let 一起用的时候,每次循环会多创建一个 i 。因为 let 变量的作用域只能在当前函数中,所以每次 for 循环生成的都是一个新的 i , setTimeout 里输出的 i 就是这个新的 i ,这个 i 是不会变化的,所以输出的就是正常的。
除了使用 for let 配合,还有什么其他方法可以打印出 0、1、2、3、4、5?
方法一:
for(i=0;i<6;i++){
let x = i
setTimeout(()=>{console.log(x)},0)
}
方法二:(闭包)
for(let i=0;i<6;i++){
!function(i){
setTimeout(()=>{console.log(i)},0)
}(i)
}
- 声明匿名函数 function(value){} 包裹 setTimeout()
- 然后再匿名函数前加上运算符
!,防止生成新的全局变量(避免污染全局) - 在匿名函数后加个 () 立即调用,并把 i 当作参数 value 传入匿名函数进行调用
方法三:
let i
for(i = 0; i<6; i++){
setTimeout((value)=>{
console.log(value)
},0,i)
}
使用setTimeout 的第三个参数(setTimeout的第三个参数作用,它就是当作setTimeout第一个函数的参数)
- 这个参数可以将自身传给第一个参数,也就是匿名函数function(value)中,作为所需要的参数value,value可默认不写。
- 而 i 共传入6次(0,1,2,3,4,5),通过匿名函数即可打印出。
- 通常不写第三个参数,如果默认不写第三个参数,则不会传入函数
- 由于每次传入的参数是从for循环里面取到的值,所以会依次输出0~5
方法四:(const关键字)
let i
for(i = 0; i<6; i++){
const x = i
setTimeout(()=>{
console.log(x)
})
}
资料来源:
饥人谷