ES6类构造函数与函数原型构造函数的区别及一致性疑问
ES6类构造函数 vs 函数式构造函数:异同详解
好问题!这俩确实容易让人混淆,我来给你拆解清楚它们的核心异同点~
先看你提到的两种场景
1. 函数式构造函数的情况
你写的这个函数式构造函数:
const Cat = function (name) { this.name = name; };
Cat本身就是构造函数,它的原型Cat.prototype默认自带一个constructor属性,指向Cat自己。- 如果你直接替换原型:
Cat.prototype = {},新的原型对象里就没有constructor了,但new Cat('Mimi')依然能正常运行——这是因为JS创建实例的核心逻辑不依赖原型上的constructor属性,而是靠new操作符后面的那个函数来初始化对象。原型上的constructor更多是个“标识”,用来告诉开发者这个实例是由哪个构造函数生成的,不是实例创建的必要条件。
2. ES6类的情况
再看类的写法:
class Dog { constructor(name) { this.name = name; } }
- 类本质上是函数的语法糖,
Dog本身就是构造函数,Dog.prototype.constructor同样默认指向Dog。 - 如果你同样替换原型:
Dog.prototype = {},原型上的constructor也会丢失,但new Dog('旺财')照样能工作,原因和函数式的情况一样——new操作符认的是你调用的那个构造函数,不是原型上的标记。
核心异同点对比
相同点
- 本质逻辑一致:不管是类还是函数式构造函数,用
new调用时,都会创建新对象、绑定this、执行构造逻辑、把实例的__proto__指向构造函数的prototype。 - 原型默认都有
constructor:两者的prototype对象初始状态下,都包含一个指向自身的constructor属性。
不同点
- 调用限制:类的构造函数必须用
new调用,直接执行Dog()会报错;而普通函数可以直接调用,此时this在非严格模式下指向全局对象,严格模式下是undefined。 - 枚举性:类的
constructor方法是不可枚举的(用Object.keys(Dog.prototype)看不到它);而普通函数原型上的constructor是可枚举的(Object.keys(Cat.prototype)能看到)。 - 方法定义规范:类内部的所有方法(包括
constructor)都会被定义在prototype上,且默认不可枚举;而普通函数如果手动往prototype加方法,默认是可枚举的(除非用Object.defineProperty手动设置不可枚举)。 - 语法糖封装:类自带
extends继承、静态方法(static关键字)等语法,这些在函数式构造函数里需要手动模拟(比如用Object.create实现继承),类帮你封装了这些底层逻辑,更简洁规范。
补充:丢失的constructor怎么恢复?
不管是函数还是类,如果你替换了原型后想恢复constructor标识,只需要手动添加即可:
// 函数式的情况 Cat.prototype = { constructor: Cat, // 手动指向Cat meow() { console.log('Meow!'); } }; // 类的情况 Dog.prototype = { constructor: Dog, // 手动指向Dog bark() { console.log('Woof!'); } };
这样一来,实例的constructor属性就会正确指向对应的构造函数了。
内容的提问来源于stack exchange,提问作者Inna Ditiashova
相关产品推荐
相关产品推荐

