题目 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 会退回到默认绑定。

规范参考

JavaScript 代码编辑器支持直接编辑或粘贴自定义代码
第 0 步 / 共 0 步
单步Space播放
按 → 单步 或 Space 自动播放
阶段 1: 编译预解析(变量提升与内存分配)
阶段 2: 代码执行(逐行赋值与调用求值)
单步执行原理解析

按键盘右方向键 “→” 进行单步调试,或按空格键 “Space” / 点击 “▶ 自动播放” 进行连续执行。