Object.create
官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create
Object.create()
方法创建一个新对象,使用现有的对象作为新创建的对象的 __proto__
。
const person = {
isHuman: true,
hello: function () {
console.log('hello!');
}
};
const me = Object.create(person);
现在对象 me 的原形指向的是对象 person:
me.__proto__ === person
// true
me.isHuman
// true
me.hello()
// hello!
用 Object.create 实现类式继承
// 父类
function Shape() {};
// 父类方法
Shape.prototype.duplicate = function() {
console.log('duplicate')
};
// 子类
function Circle(radius) {
this.radius = radius;
};
// Circle 继承 Shape
Circle.prototype = Object.create(Shape.prototype);
// 子类的方法
Circle.prototype.draw = function() {
console.log('draw');
};
现在由 Circle 构造函数生成的对象 c 具有了其父类 Shape 的属性与方法:
let c = new Circle(1);
c.duplicate()
// duplicate
来解释一下:
c.__proto__ === Circle.prototype
// true
实例 c 的 __proto__
指向 c 的构造函数 Circle
的 prototype
,这没什么问题。
那么 Circle.prototype
的 __proto__
现在指向什么呢?
我们声明了 Circle.prototype = Object.create(Shape.prototype)
;所以 Circle.prototype
的 __proto__
指向 Shape.prototype
。
Circle.prototype.__proto__ === Shape.prototype
// true
所有实例 c 的原形的原形就指向了 Shape.prototype
:
c.__proto__.__proto__ === Shape.prototype
// true
这就是继承的原理。
修正构造函数
但这个继承其实隐含了一个逻辑问题。
let c = new Circle(1);
c.constructor
// ƒ Shape() {}
现在实例 c 的构造函数 constructor
变成了 Shape()
而不是 Circle()
。从逻辑上讲实例 c 应当是构造函数 Circle()
生成的。所以我们修改了原形之后,应该重新修正构造函数。
// 父类
function Shape() {};
// 父类方法
Shape.prototype.duplicate = function() {
console.log('duplicate')
};
// 子类
function Circle(radius) {
this.radius = radius;
};
// Circle 继承 Shape
Circle.prototype = Object.create(Shape.prototype);
// 修正构造函数
Circle.prototype.construcor = Circle;
// 子类的方法
Circle.prototype.draw = function() {
console.log('draw');
};
let c = new Circle(1);
使用中间函数进行继承
我们可以用一个函数把实现继承的代码封装一下,以更便利地调用:
// 传入两个构造函数,实现继承
function extend(Child, Parent) {
Child.prototype = Object.create(Parent.prototype);
Child.prototype.construcor = Child;
}
网友评论