new构造函数与Object.create(构造函数原型)的差异及Bird实例调用getWeight方法报错原因问询
为什么用Object.create(Bird.prototype)创建的实例无法调用getWeight?new和Object.create的差异解析
先把你的代码贴出来方便分析:
function Bird() { let weight = 15; this.getWeight = () => weight } // let birb = new Bird let birb = Object.create(Bird.prototype); console.log(birb.getWeight()) // 这里会报错TypeError
先说说为啥会报错
核心原因一句话:你用Object.create的时候,根本没执行Bird这个构造函数!
咱们拆解来看:
当你用
new Bird()的时候,JS引擎会帮你做三件关键事:- 创建一个空对象,把它的
__proto__指向Bird.prototype - 把这个空对象绑定为Bird构造函数内部的
this - 执行Bird构造函数
所以构造函数里的this.getWeight = () => weight会直接把getWeight作为实例的自有属性挂到新对象上,调用的时候自然能找到。
- 创建一个空对象,把它的
但
Object.create(Bird.prototype)只做了上面的第1件事:创建一个空对象,让它的原型链指向Bird.prototype,完事儿了!它不会去执行Bird构造函数,所以这个birb对象上根本没有getWeight这个属性——毕竟getWeight是挂在构造函数的this上(也就是实例自有属性),不是挂在Bird.prototype上的。当你调用birb.getWeight()时,JS顺着原型链找也找不到这个方法,自然就报“不是函数”的错了。
再聊聊new和Object.create(构造函数.prototype)的核心差异
我整理了几个关键区别,帮你理清楚:
构造函数是否执行
new 构造函数():自动执行构造函数,并且把构造函数内部的this绑定到新创建的实例上,构造函数里所有通过this.xxx定义的内容都会成为实例的自有属性/方法。Object.create(构造函数.prototype):完全不执行构造函数,只创建一个原型指向目标的空对象,实例不会拥有构造函数里定义的任何自有属性。
实例的属性组成
- new出来的实例:同时拥有构造函数中this添加的自有属性,以及原型链上继承的属性(来自构造函数的prototype)。
- Object.create创建的实例:只有原型链上继承的属性,除非你手动调用构造函数并绑定this(比如
Bird.call(birb)),才能把构造函数里的属性挂到实例上。
this的绑定逻辑
- new操作符会自动完成this的绑定,把构造函数的this指向新实例;而Object.create本身不涉及this绑定,如果你想让构造函数里的this指向这个新对象,必须手动用
call/apply去调用构造函数。
- new操作符会自动完成this的绑定,把构造函数的this指向新实例;而Object.create本身不涉及this绑定,如果你想让构造函数里的this指向这个新对象,必须手动用
额外提一句:如果想用Object.create实现和new类似的效果怎么办?
你可以手动调用构造函数并绑定this:
function Bird() { let weight = 15; this.getWeight = () => weight } let birb = Object.create(Bird.prototype); Bird.call(birb); // 手动执行构造函数,把this绑定到birb console.log(birb.getWeight()) // 现在就能正常输出15了
内容的提问来源于stack exchange,提问作者andrew josephus
相关产品推荐
相关产品推荐

