`

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

阅读更多
本文列举了《JavaScript高级程序设计:第二版》书中讲到的6种创建JavaScript对象的模式,这里有英文版下载。
代码里边用到的一些公用方法本文后边有附。附件为源码。
1、原型链
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

2、借用构造函数
/**
 * 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

3、组合继承
/**
 * 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;
}

4、原型继承
/**
 * 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]

5、寄生继承
/**
 * 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

6、寄生组合继承
/**
 * 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

7、拷贝继承
 * 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


其他代码:
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();
	}
};


分享到:
评论

相关推荐

    JavaScript实现继承的几种方式

    本篇文章将深入探讨JavaScript中实现继承的几种常见方式。 1. 原型链继承 JavaScript的原型(prototype)机制是实现继承的基础。每个函数都有一个prototype属性,这个属性指向一个对象,这个对象的属性和方法可以被...

    学习javascript面向对象 javascript实现继承的方式

    本文将详细介绍六种实现JavaScript继承的方法。 1. 原型链继承 原型链继承是通过改变子类型的原型对象来实现继承的。子类型构造函数的原型被替换为超类型构造函数的一个实例,这样子类型就可以继承超类型的所有属性...

    javascript 原生态js类继承实现的方式

    我们还知道,面向对象编程有三个重要的概念 - 封装、继承和多态。 但是在JavaScript的世界中,所有的这一切特性似乎都不存在。 因为JavaScript本身不是面向对象的语言,而是基于对象的语言。

    【JavaScript的9种继承实现方式归纳】js实现继承的几种方式.pdf

    JavaScript 的 9 种继承实现方式归纳 JavaScript 中的继承方式是基于原型的,与基于类的编程语言,如 C++ 和 Java,截然不同。JavaScript 的灵活性使得其实现继承的方式非常多样化。本文将介绍 JavaScript 中的 9 ...

    JavaScript学习指南 高清 PDF

    原型链是JavaScript实现继承的一种方式,通过__proto__属性或Object.getPrototypeOf方法可以访问对象的原型。 3. **作用域与闭包**:作用域决定了变量在哪些代码块中可被访问,有全局作用域和局部作用域。闭包是一...

    JavaScript中实现继承的八种方式

    详细介绍了JavaScript中继承的实现方式以及其优缺点分析。

    详解Javascript继承的实现

    本文将深入探讨JavaScript继承的实现方式,以及其中的问题和解决方案。 首先,我们来看混合方式的实现,这种方式结合了原型链和对象冒充。在JavaScript中,构造函数是用于创建特定类型对象的函数。例如,`Employee`...

    JavaScript继承

    此外,JavaScript的灵活性允许开发者选择基于类的继承方式,或者利用原型继承的微妙之处,实现更高效的设计。 4.1 为什么需要继承 继承的主要目的是代码复用和降低耦合度。通过继承,可以在已有类的基础上扩展功能...

    javascript控件开发之继承关系

    在这个主题中,“javascript控件开发之继承关系”主要探讨的是如何利用JavaScript的面向对象特性来构建和组织控件的层次结构,以及如何通过继承来实现代码的复用和模块化。 在JavaScript中,继承是基于原型...

    javascript中如何实现封装,继承和多态

    javascript中如何实现封装,继承和多态

    JavaScript是如何实现继承的(六种方式)

    大多OO语言都支持两种继承方式: 接口继承和实现继承 ,而ECMAScript中无法实现接口继承,ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现,下文给大家技术js实现继承的六种方式,需要的朋友参考下

    JavaScript学习指南

    JavaScript,一种广泛应用于网页和网络应用的脚本语言,是互联网上最流行的编程语言之一。它主要用于客户端的交互式网页开发,也可以在服务器端通过Node.js平台进行后端开发。JavaScript与Java虽然名字相似,但两者...

    JavaScript继承机制研究.pdf

    JavaScript继承机制的实现方式多样化,每种继承机制都有其优缺点。通过深入理解JavaScript继承机制,可以更好地理解JavaScript面向对象编程机制,并提高开发效率。本文对JavaScript继承机制的研究将有助于读者更好地...

    JavaScript五种继承方式

    JavaScript继承第1种方式:对象冒充;第2种方式:call方法;第3种方式:apply方法;第4种方式:原型链方式;第5种方式:混合方式(推荐)

    JavaScript学习指南带书签PDF

    4. **异步编程**:JavaScript是单线程的,但通过事件循环和回调函数、Promise、async/await等方式实现异步处理,避免阻塞UI。 5. **DOM操作**:学习如何使用JavaScript来创建、修改和查找DOM元素,是网页动态化的...

    JavaScript是如何实现继承的(六种方式)_.docx

    在JavaScript中,由于其动态性质,继承的实现方式与传统的面向对象语言有所不同。本文将详细介绍JavaScript中的六种继承方式,包括它们的工作原理以及实际应用示例。 #### 二、原型链继承 **1. 原理概述** 原型链...

    浅析JavaScript实现基于原型对象的“继承”.pdf

    原型对象是JavaScript继承机制的核心。 寄生组合模式 基于原型的继承有一个缺陷,那就是它不能够很好地支持多继承。如果我们想要实现多继承,我们可以使用寄生组合模式。寄生组合模式是通过组合原型对象和构造函数...

    javascript继承之工具函数二

    这里提到的"工具函数二"可能是介绍了一种或多种继承模式的实现方式。下面我们将详细讨论这些概念: 1. **原型链继承**:这是JavaScript默认的继承方式,通过`__proto__`或`Object.create()`来实现。子对象的原型被...

Global site tag (gtag.js) - Google Analytics