✅ 被 Vue 管理的函数(如
data、methods、侦听器handler、计算属性get/set)→ 写成普通函数,this指向 vm
✅ 不被 Vue 管理的回调(定时器setTimeout/setInterval、ajax、Promise.then())→ 写成箭头函数,this才指向 vm
为什么 setTimeout 要用箭头函数?
《025_watch对比computed》文中:
watch: {
firstName(val) {
//如果此处写为普通 function,this 将是 window(undefined 严格模式)
setTimeout(() => {
console.log(this) // ✅ vm (Vue 实例)
this.fullName = val + '-' + this.lastName
}, 1000)
}
}
原因分析:
1️⃣ firstName(val){...} —— Vue 帮你调用
Vue 内部用 call(vm) 或 apply(vm) 调用这个 watcher handler,所以普通函数里 this === vm,没问题。
2️⃣ setTimeout(function(){...}) —— 浏览器调用,不是 Vue
setTimeout 的回调是浏览器异步队列调用的,普通 function 没有自身 this 绑定,会回退到:
- 非严格模式 →
window - 严格模式 →
undefined
所以不能用普通函数,否则 this.fullName 会报错。
3️⃣ 箭头函数为什么行? //★★★
箭头函数没有自己的 this,它的 this 继承 自 外层 词法作用域——也就是外层 firstName(val){...} 里的 this(即 vm),所以:
setTimeout(() => {
this.fullName = ... // this 沿作用域链找到 vm
})
记忆口诀(尚硅谷原话)
🔑 Vue 调的 → 普通函数(Vue 帮你绑 this)
🔑 JS 引擎/浏览器调的(定时器、ajax、Promise)→ 箭头函数(继承外层 this)
对照表格
| 场景 | 示例 | 推荐写法 | this 是谁 |
|---|---|---|---|
data / methods / computed / watch handler |
Vue 调用 | 普通函数 | vm |
setTimeout / setInterval |
浏览器调用 | 箭头函数 | 继承外层 → vm |
axios().then(fn) / Promise.then() |
微任务队列 | 箭头函数 | 继承外层 → vm |
自定义指令 bind(el,binding,vnode){} |
Vue 调用 | 普通函数 | vm(一般不用this) |
