面向对象精要——继承

一、原型对象链和 Object.prototype

JS 内建的继承方法被称为原型对象链(对象继承其原型对象,而原型对象继承它的原型对象,以此类推),又可称为对象继承。
当访问一个对象的属性时,JS引擎会执行一个搜索过程,如果在对象实例上发现该属性(自有属性),该属性值就会被使用,否则会搜索 [[Prototype]],如果仍然没有发现,则搜索该原型对象上的 [[Prototype]] 直到继承链末端。

上几章博客中用到的多个方法都是定义在 Object.prototype 上,因此可以被其他对象继承:

  1. hasOwnProperty() 检查是否存在一个给定名字的自有属性;
  2. propertyIsEnumerable() 检查一个自有属性是否可枚举;
  3. isPrototypeOf() 检查一个对象是否是另一个对象的原型对象
  4. valueOf() 返回一个对象的值表达
  5. toString() 返回一个对象的字符串表达
    最好不要修改 Object.prototype !!!(在 Object.prototype 上添加的方法和属性会出现在所有对象上!并且以 Object.prototype.property = anything 方式添加的属性是可枚举的,即会出现在每一个对象的 for-in 循环中)。

二、对象继承

对象继承是最简单的继承类型。唯一需要做的就是制定哪个对象时新对象的 [[Prototype]] 。
对象字面形式会隐式制定 Object.prototype 为其 [[Prototype]] ,也可以用 Object.create() 方法显式制定。
Object.create() 方法接受两个参数,1.需要被设置为新对象的 [[Prototype]] 的对象(可以为 null,即没有原型对象链),第二个可选参数是一个属性描述对象,格式和 Object.defineProperties() 中使用的一样。

var book = {
	title: "This is a book"
};
// 等同于下面代码
var book = Object.create(Object.Prototype, {
	title: {
		value: "This is a book",
		configurable: true,
		enumerable: true,
		writable: true
	}
})

三、构造函数继承

构造函数也是对象。当新建一个函数的时候,该函数的 prototype 属性被自动设置为一个新的继承自 Object.prototype 的泛用对象,该对象有一个自有属性 constructor。事实上,JavaScript 引擎做了下面的事情:

// 你定义一个函数
funcction Person(){	//do something }

// JS 在引擎中:
Person.prototype = Object.create(Object.prototype, {
	constructor: {
		value: Perosn,		//指向自身
		configurable: true,
		enumerable: true,
		writable: true
	}
})

四、构造函数窃取

构造函数窃取的关键是 call() 和 apply() 方法。只需要在子类的构造函数中用 call() 或者 apply() 调用父类的构造函数,并将新创建的对象传进去即可。实际上,就是用自己的对象窃取父类的构造函数。

function Rectangle(length, width) {
	this.length = length;
	this.width = width;
}
Rectangle.prototype.getArea = function() {
	returen this.length * this.width;
}
function Square(size) {
	//从 Rectangle 继承
	Rectangle.call(this, size, size);
	// 添加新的属性或覆盖原有属性
}
Square.prototype = Object.create(Rectangle.prototype, {
	constructor: {
		value: Square,		//指向自身
		configurable: true,
		enumerable: true,
		writable: true
	}
})
Square.prototype.getArea = function() {	//覆盖原有方法};
Square.prototype.toString = function() {	//添加新方法};

这种分两步走的过程在需要完成自定义类型之间的继承时比较有用。
一般来说,需要修改 prototype 来继承方法并用构造函数窃取来设置属性。由于这种做法模仿了那些基于类的语言的类继承,通常被称作伪类继承。

五、访问父类方法

可以通过直接访问父类原型对象的方式访问父类的方法,当这么做时,必须以 call() 或 apply() 执行父类方法并传入一个子类的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值