题目 21 / 31
为什么解构出来的 getName 仍然认得实例?
知识点: this 绑定难度: 高级
在构造函数内部创建的箭头函数,会永久捕获那次构造调用的 this。
使用执行可视化器解题在下方逐步观察每个绑定、函数调用和控制台输出。预测输出结果
预测两行输出。第二次调用把 getName 从 cat 上解构出来后再调用——它还能正常工作吗?
function Pet(name) {
this.name = name;
this.getName = () => this.name;
}
const cat = new Pet('Fluffy');
console.log(cat.getName());
const { getName } = cat;
console.log(getName());查看答案与完整解析
正确输出
Fluffy
Fluffy为什么会这样
new Pet('Fluffy') 触发 Construct 操作:一个全新对象被分配出来,并作为 this 绑定到这次 Pet 调用上,this.name 被设置为 'Fluffy'。
this.getName = () => this.name 是在 Pet 执行期间创建的箭头函数。箭头函数没有属于自己的 this——它以词法方式捕获了外层 Pet 调用当时的 this,也就是这个刚创建出来的实例,并且永久保留。
cat.getName() 打印 'Fluffy'。const { getName } = cat 这次解构只是把函数值复制了出来;箭头函数捕获的 this 并不依赖之后如何或在哪里调用它,所以单独调用 getName() 同样打印 'Fluffy'。
这道题考察什么
- new 会在整个构造调用期间把 this 绑定到新创建的实例
- 构造函数内部定义的箭头函数会把这个实例永久锁定为 this
- 和普通方法不同,被解构出来的箭头函数不会丢失 this
运行环境前提
这个行为是箭头函数特有的;如果 getName 换成普通方法,把它解构出来调用就会丢失实例,this 会退回到默认绑定。