JavaScript学习之三 — JavaScript实现继承的7种方式

本文列举了[url=http://www.china-pub.com/196857&ref=hotsale]《JavaScript高级程序设计:第二版》[/url]书中讲到的6种创建JavaScript对象的模式,[url=http://ajava.org/book/javascript/17807.html]这里[/url]有英文版下载。
代码里边用到的一些公用方法本文后边有附。附件为源码。
[size=medium][b]1、原型链[/b][/size]

Gmis.inheritance.Animal = function(nickname, legCount, characters) {
this.nickname = nickname;
this.legCount = legCount;
this.characters = characters;
}
Gmis.inheritance.Animal.prototype = {
constructor : Gmis.inheritance.Animal,
getNickName : function() {
return this.nickname;
},
getLegCount : function() {
return this.legCount;
},
getCharacters : function() {
return this.characters;
},
getCharacterString : function() {
return "[" + (this.characters == undefined ? "undefined" : this.characters.join(",")) +"]";
},
toString : function() {
return "nickname: " + this.getNickName() + ", legCount: " + this.getLegCount() + ", charachters: "
+ this.getCharacterString();
}
};
/**
* 1、原型链<br>
* 优点:继承了超类的方法--在通过new创建实例的时候,已经给实例添加了一个指向原型的属性,对原型方法的调用都是通过该隐藏实例查找过去的<br>
* 缺点:<br>
* 1、没有继承超类的属性<br>
* 2、实例的构造函数是超类的构造函数<br>
*
* @param {String} type
* @param {int} legCount
*/
Gmis.inheritance.Cat = function(nickname, legCount) {
this.nickname = nickname;
this.legCount = (legCount == undefined) ? 4 : legCount;
};
Gmis.inheritance.Cat.prototype = new Gmis.inheritance.Animal();
var cat = new Gmis.inheritance.Cat("jiafei", 4, ['lovely', 'agile']);
Gmis.inheritance.util.printAnimal("1、原型链", cat.toString());
Gmis.util.printMessage("Gmis.inheritance.Cat.prototype.constructor:\n" + Gmis.inheritance.Cat.prototype.constructor);
Gmis.util.printMessage("cat.constructor:\n" + cat.constructor);
Gmis.util.printMessage("Gmis.inheritance.Cat.prototype.constructor"
+ (Gmis.inheritance.Cat.prototype.constructor === cat.constructor ? " === " : " !== ") + "cat.constructor: ");


1、原型链 nickname: jiafei, legCount: 4, charachters: [undefined]
Gmis.inheritance.Cat.prototype.constructor:
function (nickname, legCount, characters) {
this.nickname = nickname;
this.legCount = legCount;
this.characters = characters;
}
cat.constructor:
function (nickname, legCount, characters) {
this.nickname = nickname;
this.legCount = legCount;
this.characters = characters;
}
Gmis.inheritance.Cat.prototype.constructor === cat.constructor

[size=medium][b]2、借用构造函数[/b][/size]

/**
* 2、借用构造函数<br>
* 优点:可以继承属性<br>
* 缺点:不能继承方法<br>
*
* @param {String} nickname
* @param {int} legCount
*/
Gmis.inheritance.Dog = function(nickname, legCount) {
Gmis.inheritance.Animal.call(this, nickname, legCount);
};
Gmis.inheritance.Dog.prototype.toString = function() {
return "Dog.... nickname: " + this.nickname + ", legCount: " + this.legCount;
};
var dog = new Gmis.inheritance.Dog("huhu", 4);
Gmis.inheritance.util.printAnimal("2、借用构造函数", dog.toString());

2、借用构造函数 Dog.... nickname: huhu, legCount: 4

[size=medium][b]3、组合继承[/b][/size]

/**
* 3、组合继承--组合借用构造函数和原型链两种方式,各取其利<br>
* 优点:<br>
* 1、可以继承属性<br>
* 2、可以继承方法<br>
* 3、子类的构造函数指向子类本身<br>
* 缺点:<br>
* 1、调用了两次超类构造函数,如下所示,分别在a1、a2出调用了超类构造函数<br>
* 2、覆盖超类的方法的时候,没有办法在复用超类方法的基础上添加新的功能,如下toString方法<br>
*
* @param {String} nickname
* @param {int} legCount
* @param {String} desc
*/
Gmis.inheritance.Pig = function(nickname, legCount, characters, desc) {
// a1、第二次调用构造函数
Gmis.inheritance.Animal.call(this, nickname, legCount, characters);
this.desc = desc;
};
// a2、第一次调用构造函数
Gmis.inheritance.Pig.prototype = new Gmis.inheritance.Animal();
Gmis.inheritance.Pig.prototype.constructor = Gmis.inheritance.Pig;
Gmis.inheritance.Pig.prototype.getDesc = function() {
return this.desc;
};
Gmis.inheritance.Pig.prototype.toString = function() {
// 如果return this.toString() + ", desc: " + desc;会陷入死循环的,又没有超类的引用,无法super.toString()
return "nickname: " + this.getNickName() + ", legCount: " + this.getLegCount() + ", charachters: "
+ this.getCharacterString() + ", desc: " + this.getDesc();
};
var pig = new Gmis.inheritance.Pig('pipi', 4, ['fat', 'sleepy'], 'lovely');
Gmis.inheritance.util.printAnimal("3、组合继承", pig.toString());
Gmis.util.printMessage("pig.constructor:\n" + pig.constructor);

3、组合继承 nickname: pipi, legCount: 4, charachters: [fat,sleepy], desc: lovely
pig.constructor:
function (nickname, legCount, characters, desc) {
// a1、第二次调用构造函数
Gmis.inheritance.Animal.call(this, nickname, legCount, characters);
this.desc = desc;
}

[size=medium][b]4、原型继承[/b][/size]
/**
* 4、原型继承<br>
* 优点:实现简单的拷贝<br>
* 缺点: 1、无法扩展<br>
* 2、所有实例共用引用类型的属性值<br>
*
* @param {Object} instance
* @return {Object}
*/
Gmis.inheritance.createSubInstance = function(instance) {
var F = function() {};
F.prototype = instance;
return new F();
};
var animal = new Gmis.inheritance.Animal('turkey', 2, ['beautiful', 'agile']);
var chick = Gmis.inheritance.createSubInstance(animal);
var chick2 = Gmis.inheritance.createSubInstance(animal);
// 新加的属性也会出现到chick中
chick2.getCharacters().push('fan');
Gmis.inheritance.util.printAnimal("4、原型继承", chick.toString());

4、原型继承 nickname: turkey, legCount: 2, charachters: [beautiful,agile,fan]

[size=medium][b]5、寄生继承[/b][/size]

/**
* 5、寄生继承<br>
* 优点:可以扩展属性和方法<br>
* 缺点:<br>
* 1、所有实例共用引用类型的属性值<br>
*
* @param {Object} instance
* @return {}
*/
Gmis.inheritance.createExtensionSubInstance = function(instance, wingCount) {
var F = function(wingCount) {
this.wingCount = wingCount
};
F.prototype = instance;
F.prototype.getWingCount = function() {
return this.wingCount;
}
F.prototype.toString = function() {
return "nickname: " + this.getNickName() + ", legCount: " + this.getLegCount() + ", charachters: "
+ this.getCharacterString() + ", wingCount: " + this.getWingCount();
}
return new F(wingCount);
};
var animal = new Gmis.inheritance.Animal('quail', 2, ['beautiful', 'agile']);
var quail = Gmis.inheritance.createExtensionSubInstance(animal, 2);
Gmis.inheritance.util.printAnimal("5、寄生继承", quail.toString());

5、寄生继承 nickname: quail, legCount: 2, charachters: [beautiful,agile], wingCount: 2

[size=medium][b]6、寄生组合继承[/b][/size]

/**
* 6、寄生组合继承 -- 通过原型继承方法, 通过借用构造函数继承属性<br>
* 优点:<br>
* 1、解决5的缺点1,实例不共用引用类型的属性<br>
* 2、解决3的缺点1,只调用一次构造函数<br>
* 注:Ext.extend用的就是这种方式<br>
*/
Gmis.inheritance.extend = function(subType, superType) {
subType.prototype = Gmis.inheritance.createSubInstance(superType.prototype);
subType.prototype.constructor = subType;
};
Gmis.inheritance.Rabbit = function(nickname, legCount, characters, desc) {
Gmis.inheritance.Animal.call(this, nickname, legCount, characters);
this.desc = desc;
if (!this.getDesc) {
Gmis.inheritance.Rabbit.prototype.getDesc = function() {
return this.desc;
};
Gmis.inheritance.Rabbit.prototype.toString = function() {
return "nickname: " + this.getNickName() + ", legCount: " + this.getLegCount() + ", charachters: "
+ this.getCharacterString() + ", desc: " + this.getDesc();
};
}
};
//不能把这一行代码放在构造函数里边,因为在运行构造函数的开始处已经给实例原型属性赋了值
Gmis.inheritance.extend(Gmis.inheritance.Rabbit, Gmis.inheritance.Animal);
var rabbit = new Gmis.inheritance.Rabbit("tutu", 4, ['quick', 'red eyes'], 'desc');
var rabbit2 = new Gmis.inheritance.Rabbit("tutu2", 4, ['quick2', 'red eyes2'], 'desc2');
//这个实例属性的设置不会影响到rabbit实例
rabbit2.getCharacters().push("charachter3");
Gmis.inheritance.util.printAnimal("6、寄生组合继承", rabbit.toString());

6、寄生组合继承 nickname: tutu, legCount: 4, charachters: [quick,red eyes], desc: desc

[size=medium][b]7、拷贝继承[/b][/size]

* 7、拷贝继承--实则是拷贝,可以用来实现多继承
* @param {Object} subInstance
* @param {Object} superInstance
*/
Gmis.inheritance.copyInherite = function(subInstance,superInstance){
for(var name in superInstance){
if(!(name in subInstance)){
subInstance[name] = superInstance[name];
}
}
}
Gmis.inheritance.Racer = function(){
if(!this.run){
Gmis.inheritance.Racer.prototype.run = function(){
return this.nickname + " is running";
}
}
};
Gmis.inheritance.copyInherite(rabbit,new Gmis.inheritance.Racer());
Gmis.inheritance.util.printAnimal("7、拷贝继承", rabbit.toString() + ", " + rabbit.run());

7、拷贝继承 nickname: tutu, legCount: 4, charachters: [quick,red eyes], desc: desc, tutu is running


[b][size=medium]其他代码:[/size][/b]

Gmis = {};
Gmis.inheritance = {};
Gmis.inheritance.util = {};
Gmis.util = {};

Gmis.inheritance.util.printAnimal = function(type, message) {
Gmis.util.printMessage(message == undefined ? type : type + " " + message);
};
Gmis.util.printMessage = function(message) {
message += "\n";
var output = document.getElementById("output");
output.innerText = output.innerText == null ? message : output.innerText + message;
}
Gmis.inheritance.Animal = function(nickname, legCount, characters) {
this.nickname = nickname;
this.legCount = legCount;
this.characters = characters;
}
Gmis.inheritance.Animal.prototype = {
constructor : Gmis.inheritance.Animal,
getNickName : function() {
return this.nickname;
},
getLegCount : function() {
return this.legCount;
},
getCharacters : function() {
return this.characters;
},
getCharacterString : function() {
return "[" + (this.characters == undefined ? "undefined" : this.characters.join(",")) +"]";
},
toString : function() {
return "nickname: " + this.getNickName() + ", legCount: " + this.getLegCount() + ", charachters: "
+ this.getCharacterString();
}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值