You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS中构造函数原型对象与类原型对象的差异疑问

为什么直接给类的prototype赋值对象不生效,但构造函数可以?

本质差异在于普通函数构造器和ES6 class的prototype属性的可写性不同,这是ES6规范刻意设计的区别:

1. 普通构造函数的prototype是可写的

普通函数的prototype是一个可配置、可写的自有属性。当你执行ex.prototype = o1时,会直接替换掉构造函数原本的原型对象。
用new ex()创建实例时,实例的[[Prototype]]会直接指向构造函数当前的prototype值(也就是o1),所以o2能继承o1的sayHi、sayBye方法。

2. ES6 class的prototype是不可写的

ES6 class的prototype属性被规范设置为不可写(writable: false)。你可以通过以下代码验证:

console.log(Object.getOwnPropertyDescriptor(example, 'prototype'));
// 输出:{ value: {}, writable: false, enumerable: false, configurable: false }

当你尝试example.prototype = o1时:

  • 严格模式下会直接抛出TypeError
  • 非严格模式下会静默失败,class的原型对象根本不会被替换

因此用new example()创建的实例e,它的[[Prototype]]依然指向class默认的原型对象,而非o1,自然无法继承o1的方法。

为什么Object.setPrototypeOf能生效?

Object.setPrototypeOf(example.prototype, o1)不是替换example.prototype本身,而是修改它的原型链上层——把o1设为example.prototype的原型。这种操作不修改example.prototype属性本身的可写性,只是调整原型链关系,所以能让实例间接继承o1的方法,同时保留class原原型上的属性(比如constructor)。

这种设计是ES6规范的刻意限制,目的是避免随意替换class原型破坏其内部机制(比如继承、super的正常工作),让class的行为更符合面向对象的封装特性。

内容的提问来源于stack exchange,提问作者curiousmind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:43:21