当在任何对象上调用任何属性时,JavaScript 引擎将首先在该对象中查找该属性(即该对象自己的、非继承的属性)。如果没有找到该属性,JavaScript 将查看该对象的原型
。如果在对象原型中仍然找不到该属性,则 JavaScript 将在原型链上继续搜索。JavaScript 中的继承重点就是建立原型链
。
如果只继承原型呢?
假设我们希望一个 Child
对象从一个 Parent
对象继承。为什么不应该只设置 Child.prototype = Parent.prototype
呢?
对象是通过引用来传递的
。这意味着,由于 Child.prototype
对象和 Parent.prototype
对象引用的是同一个对象
,因此你对 Child
的原型所作的任何更改也会被应用于 Parent
的原型!我们可不希望子对象能够修改其父对象的属性
!最重要的是,这样做不会创建原型链。
function GuineaPig (name) {
this.name = name;
this.isCute = true;
}
const waffle = new GuineaPig('Waffle');
// waffle.__proto__ 指向 GuineaPig.prototype
当 GuineaPig
的新实例被创建时,特殊属性 waffle.__proto__
会被设置为 GuineaPig.prototype
。这个秘密链接允许 GuineaPig
构造函数的实例访问 GuineaPig.prototype
的属性。请记住,你不应该在你编写的任何代码中使用 __proto__
。
Object.create()
我们可以借助一种方式来自己设置对象的原型:使用 Object.create()
。而且最棒的是,这种方式既可以让我们管理继承,同时又不会改变原型!
Object.create()
会接受一个对象作为参数,并返回一个新的对象,其 __proto__
属性会被设置为传递给它的参数。然后,你只需要将所返回的对象设置为子对象构造函数的原型即可。
const mammal = {
vertebrate: true,
earBones: 3
};
const rabbit = Object.create(mammal);
console.log(rabbit); //{}
console.log(rabbit.__proto__ === mammal); //true
这意味着,现在 rabbit
扩展了 mammal
(即 rabbit
继承自 mammal
),而且 rabbit
可以将 mammal
的属性当作自己的属性一样进行访问!
Object.create()
是在 JavaScript 中建立原型继承的一种实用方法。
JavaScript 中的继承重点就是建立原型链
。这让我们可以子类化
,也就是创建一个“子”对象,让它继承“父”对象的大部分或全部属性和方法。然后,我们可以分别实现任何子对象的独特属性和方法,同时仍然保留其父对象的数据和功能。