答:this是undefined,要更改的属性会报TypeError错误, Cannot read property 'xxx' of undefined。
因为箭头函数默绑定父级作用域的上下文,所以不会绑定vue实例,所以 this 是undefind。
不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。
下面从源码角度分析一下:
我们配置的watch选项,所写的处理函数会创建watcher实例,把处理函数挂载给watcher,方法名叫cb。
下面这个run方法是watcher的原型方法,被观测的目标发生变化时,即你watch的属性变化时,它会通知它的dep中所有的watcher,执行update,然后立即执行下面这个run,重新计算你watch的属性的值,再次进行依赖收集,如果求出的新值和旧值不一样了,那么会执行cb,如下所示
run() {
if (!this.active) return
var value = this.get();
if (value !== this.value || isObject(value) || this.deep) {
var oldValue = this.value; // oldValue保存旧值
this.value = value; // this.value更新为新值
if (this.user) {
// 如果当前watcher是开发者定义的,即通过watch选项或$watch创建的watcher的cb是开发者编写的
// 则行为不可预知,所以执行cb回调时try...catch一下,发生错误能给开发者一个友好的提示
try { // 开发者编写的回调接收到被观察目标的新值和旧值
this.cb.call(this.vm, value, oldValue)
} catch (e) {
handleError(e, this.vm, `callback for watcher "${this.expression}"`)
}
} else { // 不是用户创建的watcher,即渲染函数的watcher或计算属性的watcher
this.cb.call(this.vm, value, oldValue) // 直接执行回调
}
}
};
那么问题来了,如果cb不是箭头函数,那么它.call执行,执行时的this是能指定vm实例的
源码就是这么做,才把配置的函数中的this指向了vm实例
但如果是箭头函数,情况就不一样了,看下面例子。
function athis(){
console.log(this === obj)
}
const bthis =()=>{
console.log(this === obj)
}
athis.call(obj) // true
bthis.call(obj) // false
可见,你是无法将箭头函数执行中的this改绑定的,它只能从上级上下文去取this