JavaScript#JavaScript#this#异步
JavaScript 入门第十三天:this 与异步执行顺序
整理 this 的常见绑定规则、call/apply/bind 的差异,以及定时器和事件回调为何晚于同步代码执行。
2 分钟阅读
第十三天把两个常见难点放在一起:this 取决于函数如何被调用,异步回调则不会阻塞当前同步代码。关键都在“执行发生在哪里、什么时候发生”。
this 先看调用方式
普通函数中,最实用的判断方法是找调用点:
const user = {
name: '小林',
introduce() {
console.log(this.name)
},
}
user.introduce() // this 是 user
同一个函数脱离对象再调用,this 的结果会改变;严格模式下普通函数直接调用时通常为 undefined。因此不要只看函数写在哪里,也要看它实际怎样执行。
call、apply、bind 明确指定上下文
call 立即调用并逐个传参,apply 立即调用但以数组传参,bind 返回一个已绑定的新函数:
function greet(prefix) {
return `${prefix},${this.name}`
}
greet.call({ name: '阿远' }, '你好')
greet.apply({ name: '阿远' }, ['你好'])
const greetUser = greet.bind({ name: '阿远' })
箭头函数没有自己的 this,它使用定义时外层的 this,所以不能通过 call 或 bind 改变。事件处理器若需要当前触发事件的元素,使用普通函数更符合预期。
异步回调会在同步任务之后运行
定时器回调不是“延迟期间阻塞页面”,而是等待时间到后再排队执行:
setTimeout(() => {
console.log('异步回调')
}, 0)
console.log('同步代码')
输出总是先看到“同步代码”。0 只表示最快可以排队,不表示立即插队。网络请求、文件读取和事件回调也都需要把“发起操作”和“收到结果后处理”分开。
今天之后,分析问题的顺序可以固定下来:对于 this,先找调用方式;对于异步,先区分当前同步步骤和稍后执行的回调。它们都不该靠感觉猜。