首先讲讲JS函数的几大要素:
- 调用时机:JS函数的不同执行时机,会影响到函数运行的输出结果,不能通过代码本身百分百判断函数输出什么,而是要根据函数具体的执行时机。
- 作用域:每个函数都会默认创建一个作用域
- 闭包:JS函数会就近寻找最近的变量
- 形式参数
- 返回值
- 调用栈:进入一个函数的时候,要先把环境存下来,才能进去,有的东西越多,需要一个数组来保存,那保存的环境所在的数组叫做调用栈
- 函数提升
- arguments(除了箭头函数)
- this(除了箭头函数)
而一个函数的调用时机会影响其调用的结果。
从函数调用的角度,可以把函数分为同步函数和异步函数。
- 同步函数:同步函数执行时,当该函数被调用时不会立即返回,而是直到该函数所要做的事情全都做完了才返回。
-
异步函数:异步函数被调用时,该函数会立即返回尽管该函数规定的操作任务还没有完成。
比如如下代码:
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
打印结果是6个6
因为setTimeout是一个异步函数,它内部的操作并不会在其被调用时立即执行,每一次循环中,它的打印任务都被放在一个队列中,只有当for循环结束后才会开始从队列中取出任务并打印i,而此时i为6了。
那如果想要让上述代码打印 0、1、2、3、4、5,可以改成如下:
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
// 这里i被定义在循环中,故每次循环时i都有一个单独的作用域
也可以利用const参数:
let i = 0
for(i = 0; i < 6; i++){
const x = i
setTimeout(()=>{
console.log(x)
})
}
参考自:
《写代码啦》课程