js中的面向对象编程(二)

对象中的继承问题

ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的

1.原型链

实现原型链的一种基本模式

function SuperType(){
	this.property = true;
}

SuperType.prototype.getSuperVal = function(){
	return this.property
}

function SubType(){
	this.subproperty = false;
}
//继承SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubVal = function(){
	return this.subproperty;
}

var instance = new SubType();
console.log(instance.getSuperVal()); //true

以上代码定义了两个类型:SuperType和SubType,每个类型都要一个方法和属性。其中SubType通过创建SuperType实例继承了SuperType,并将该实例赋给SubType.prototype实现的。换句话说就是原本存在于SuperType中的属性和方法现在也存在于SubType.prototype中。

1.1确定原型与实例的关系

  • 第一种方式是使用instanceof操作符
console.log(instance instanceof Object); //true
console.log(instance instanceof SuperType); //true
console.log(instance instanceof SubType); //true

由原型链的关系,我们可以说instance是Object、SuperType或SubType种任一类型的实例

  • 第二种方式是使用isPrototypeOf()方法
console.log(Object.prototype.isPrototypeOf(instance));//true
console.log(SuperType.prototype.isPrototypeOf(instance));//true
console.log(SubType.prototype.isPrototypeOf(instance));//true

只要是 原型链种出现过的原型,都可以说是该原型链所派生的实例的原型

1.2谨慎地定义方法

子类型有时候需要覆盖父类型种的某个方法,或需要添加父类型不存在的某个方法。只要是给原型添加方法的代码一定要放在替换原型的语句之后。

function SuperType(){
	this.property = true;
}

SuperType.prototype.getSuperVal = function(){
	return this.property
}

function SubType(){
	this.subproperty = false;
}
// 继承SuperType
SubType.prototype = new SuperType();
// 添加新的方法
SubType.prototype.getSubVal = function(){
	return this.subproperty;
}
// 重写父类型中的方法
SubType.protptype.getSuperVal = function(){
	return false;
}
var instance = new SubType();
console.log(instance.getSuperVal()); //false

当通过SubType的实例调用getSuperVal()时,调用的是重新定义的那个方法,但当使用SuperType的实例调用getSuperVal()时,还会继续调用原来那个方法

var instance2 = new SuperType();
console.log(instance2.getSuperVal());//false

【注】:当通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这样会重写原型链

function SuperType(){
	this.property = true;
}
SuperType.prototype.getSuperVal = function(){
	return this.property;
}

function SubType(){
	this.subproperty = false;
}
//继承SuperType
SubType.prototype = new SuperType();
//使用字面量添加方法,会使上一行继承代码失效
SubType.prototype = {
	getSubVal:function(){
		return this.subproperty;
	},
	otherMethod:function(){
		return false;
	}
}
var instance = new SubType();
console.log(instance.getSuperVal()); //error

1.3原型链的问题

  • 包含引用类型值的原型
  • 在创建子类的实例时,没有办法在不影响所有对象实例的情况下,给父类型的构造函数传递参数

1.4解决原型链的问题

1.4.1 借助构造函数

在子类型的构造函数中调用父类型的构造函数

function SuperType() {
  this.color = ["red", "yellow", "black"];
}
function SubType() {
  // 利用call改变this指向实现继承
  SuperType.call(this);
}

var instance = new SubType();
instance.color.push("green");
console.log(instance.color); //red,yello,blcak,green

var instance2 = new SubType();
console.log(instance2.color); //red,yellow,black

var instance3 = new SuperType();
console.log(instance3.color); //red,yellow,black

2.继承的定义方式

2.1组合继承

组合继承指的是将原型链和构造方法技术组合在一起
实现思路:使用原型链实现对原型属性和方法的继承,使用构造方法来实现对实例属性的继承

function SuperType(name) {
  this.name = name;
  this.color = ["red", "yellow", "black"];
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
};
function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;
}
// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
  console.log(this.age);
};
var instance = new SubType("zhangsan", 22);
instance.color.push("green");
instance.sayName(); //zhangsan
instance.sayAge(); //22
console.log(instance.color); // red,yellow,black,green

var instance2 = new SubType("lisi", 23);
instance2.sayName(); //lisi
instance2.sayAge(); //23
console.log(instance2.color); // red,yellow,black

2.2原型式继承

实现思路:原型基于已有的对象创建新对象,而不必因此创建自定义类型

function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
var person = {
  name: 'zhangsan',
  friends: ['lisi', 'wangwu'],
};

var person2 = object(person);
person2.name = 'andy';
person2.friends.push('zhaoliu');

var person3 = object(person);
person3.name = 'Linda';
person3.friends.push('lihua');

console.log(person.friends); //lisi,wangwu,zhaoliu,lihua

【注】:这种做法必须要有一个对象作为另一个对象的基础,上述代码中person对象就是作为另一个对象的基础

2.3寄生式继承

实现思路:创建一个仅用于封装继承过程的函数,在这个函数的内部增强对象,最后将增强后的对象返回

function object(o){
	function F(){}
	F.prototype = o;
	return new F();
}

function createObj(original){
	var clone = new object(original);
	clone.sayHi = function(){
		console.log('hi');
	}
	return clone;
}

var person = {
	name:"zhangsan",
	friends:["lisi","wangwu"]
}

var anotherPerson = createObj(person)
anotherPerson.sayHi();

2.4寄生组合式继承

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'green'];
}
SuperType.prototype.sayName = function () {
  console.log(this.name);
};
function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function () {
  console.log(this.age);
};
var instance = new SubType('zhangsan', 22);
instance.sayName();
instance.sayAge();

链接:
1.参考JavaScript高级程序设计(第三版)
2.廖雪峰JavaScript教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值