javascript——面向对象程序设计(4)
<script type="text/javascript">
//1、继承
//2、原型链
//3、借用构造函数
//4、组合继承
//5、原型式继承
//6、寄生式继承
//7、寄生组合式继承 //1、继承是OO中最让人津津乐道的概念。许多OO语言都支持两种继承方式:接口继承和实现继承。
//接口继承只支持方法签名,而实现继承则继承实际的方法。
//由于函数没有签名,所以在ECMAScript中无法实现接口继承,只支持实现继承,而且其实现继承主要由原型链来实现。 //2、原型链。
//简单回顾一下,构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针
//而实例都包含一个指向原型对象的内部指针。
//而如果我们让原型对象指向另一个类型的实例,结果会怎样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,
//相应的,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,
//就构成了实例与原型的链条。这就是所谓原型链的基本概念。eg: //动物类
function Animal() {
this.shout = "不知道";
}
Animal.prototype.getAnimalValue = function () {
return this.shout;
} //狗狗类
function Dog() {
this.dogShout = "汪汪汪~";
} ///狗狗类继承动物类
Dog.prototype = new Animal(); Dog.prototype.getDogValue = function () {
return this.dogShout;
} var instance = new Dog();
//狗狗类调用动物类叫的方法
alert(instance.getAnimalValue())
//instance.getAnimalValue()会经历3个步骤,1、搜索实例 2、搜索Dog.prototype 3、搜索Animal.prototype
//a、别忘记默认的原型。大家要记住,所有的函数的默认原型都是Object的实例,因此默认原型都会有一个内部指针,
//指向Object.prototype。这也正是自定义类都会继承toString()和valueOf()的方法的根本原因 //b、确定原型和实例的关系
alert(instance instanceof Object);//true
alert(instance instanceof Animal);//true
alert(instance instanceof Dog);//true alert(Object.prototype.isPrototypeOf(instance));//true
alert(Animal.prototype.isPrototypeOf(instance));//true
alert(Dog.prototype.isPrototypeOf(instance));//true //c、原型链的问题
//想必大家还记得,前面介绍过含引用类型值的原型会被所有的实例共享,
//这也是为什么要在构造函数中,而不是在原型对象中定义属性的原因。
//所以,实践中很少有人单独使用原型链。 //3、借用构造函数(又叫:伪造对象或经典继承)
//这种继承的方式很简单,就是在子类构造函数内部调用超类构造函数使用call或apply
function Animal() {
this.colors = ['red', 'blue', 'green'];
} function Dog() {
//继承了Animal类
Animal.call(this);
} var dog = new Dog();
dog.colors.push("black");
alert(dog.colors);//'red','blue','green','black' var dog2 = new Dog();
alert(dog2.colors);//'red','blue','green' //相对于原型链而言,借用构造函数有很大的优势,即可以在子类构造函数中向超类传递参数
function Animal2(name) {
this.name = name;
} function Dog2() {
//继承了Animal类
Animal2.call(this, "大黄");
this.age = 2;
} var dog = new Dog2();
alert("年龄:" + dog.age + ",名称:" + dog.name); //因为方法都在构造函数中定义,因此函数复用就无从谈起了。而且在超类原型中定义的方法,对于子类型而言也是不可见的
//结果所有类型都只能使用构造函数模式。
//考虑到这些问题,借用构造函数的技术也很少单独使用。 //4、组合继承
function Animal3(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
} Animal3.prototype.sayName = function () {
alert(this.name)
} function Dog3(name, age) {
//继承属性
Animal3.call(this, name);
this.age = age;
}
//继承方法
Dog3.prototype = new Animal3();
Dog3.prototype.constructor = Dog3;
Dog3.prototype.sayAge = function () {
alert(this.age)
} var d3 = new Dog3("小黄", 1);
d3.colors.push("black");
alert(d3.colors);//red,blue,green,black
d3.sayAge();//
d3.sayName();//小黄 //组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为javascript中最常用继承方式
//而且instanceof 和 isPrototypeOf也能够用于识别基于组合继承创建的对象。 //5、原型式继承
//在没有必要兴师动众的创建构造函数,而只想让一个对象与另一个对象保持类似的情况下,原型式继承是完全可以胜任的
//不过别忘了:包含引用类型的值的属性始终都会共享相应的值,就像使用原型模式一样。 var Person={
name:'xulei',
friends:['张三','李四','王五']
} var p1=Object.create(Person);
p1.name="徐磊1";
p1.friends.push("killey");
var p2=Object.create(Person);
p2.name="徐磊2";
p2.friends.push("jack"); alert("p1.name:"+p1.name);//徐磊1
alert("p1.friends:"+p1.friends);//张三','李四','王五','killey','jack'
alert("p2.name:"+p2.name);//徐磊2
alert("p2.friends:"+p2.friends);//张三','李四','王五','killey','jack' //6、寄生式继承
//寄生式继承是与原型式继承紧密相关的一种思路。寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数
//该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。eg:
function object(o) {
function F() { }
F.prototype=o;
return new F();
}
function createAnother(original){
var clone=object(original);//通过调用函数来创建一个新对象
clone.sayHi=function(){//以某种方式来增强这个对象
alert("hi");
};
return clone;//返回这个对象
}
var Person2={
name:'xulei',
friends:['张三','李四','王五']
} var p3=createAnother(Person2);
p3.sayHi(); //7、寄生组合式继承
//前面说过,组合继承是最常用继承模式,不过它也有自己的不足。
//组合继承最大的问题就是无论在什么情况下,都会调用两次超类型的构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部
//eg:
function SuperType(name){
this.name=name;
this.colors=['red','blue','green'];
} SuperType.prototype.sayName=function(){
alert(this.name);
} function SubType(name,age) {
SuperType.call(this,name);//第二次调用SuperType
this.age=age;
} SubType.prototype=new SuperType();//第一次调用SuperType
SubType.prototype.constructor=SubType;
SubType.prototype.sayAge=function(){
alert(this.age);
} //好在已经有更好的解决方案————寄生组合式继承
//所谓寄生组合式继承就是借用构造函数来继承属性,通过原型链的混成形式来继承方法。
//其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非是超类型原型的一个副本而已
//本质上,就是使用寄生继承来继承超类型的原型,然后再将结果指定给子类型的原型。eg:
function object(o) {
function F() { }
F.prototype=o;
return new F();
}
function inheritPrototype(subType,superType) {
var prototype=object(superType.prototype);//创建对象
prototype.constructor=subType;//增强对象
subType.prototype=prototype;//指定对象
} function SuperType(name){
this.name=name;
this.colors=['red','blue','green'];
} SuperType.prototype.sayName=function(){
alert(this.name);
} function SubType(name,age) {
SuperType.call(this,name);
this.age=age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge=function(){
alert(this.age);
} var p4=new SubType("张三",29);
p4.sayName();
//这个例子的高效率体现在它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上创建不必要的、多余的属性
//与此同时,原型链还能保持不变;因此还能正常的使用instanceOf 和isPrototypeOf
//普遍认为寄生组合继承是引用类型最理想的继承方式。 </script>
javascript——面向对象程序设计(4)的更多相关文章
- JavaScript 面向对象程序设计(下)——继承与多态 【转】
JavaScript 面向对象程序设计(下)--继承与多态 前面我们讨论了如何在 JavaScript 语言中实现对私有实例成员.公有实例成员.私有静态成员.公有静态成员和静态类的封装.这次我们来讨论 ...
- JavaScript面向对象程序设计:数组
或许你会奇怪,面向对象的程序设计为什么从数组开始讲起?这是因为……其间的种种关系吧……嘿嘿,这里先卖个关子,先来看看我们熟悉的数组在JavaScript里面是什么样子的. 1. 创建数组 在J ...
- javascript面向对象程序设计系列(一)---创建对象
javascript是一种基于对象的语言,但它没有类的概念,所以又和实际面向对象的语言有区别,面向对象是javascript中的难点之一.现在就我所理解的总结一下,便于以后复习: 一.创建对象 1.创 ...
- [TimLinux] JavaScript 面向对象程序设计
1. 面向对象 面向对象语言有一个标志:都有类的概念.通过类可以创建任意多个具有相同属性和方法的对象.ECMAScript中没有类的概念,因此JavaScript中的对象夜雨基于类的语言中的面向对象有 ...
- javascript——面向对象程序设计(3)
<script type="text/javascript"> //1.结合使用构造函数模式和原型模式 //2.动态原型模式 //3.寄生构造函数模式 //4.稳妥构造 ...
- javascript——面向对象程序设计(2)
<script type="text/javascript"> //1.理解原型对象 //2.原型与in操作符 //3.更简单的原型语法 //4.原型的动态性 //5. ...
- javascript——面向对象程序设计(1)
<script type="text/javascript"> //ECMA-262把对象定义为:“无序属性的 集合,其属性可以包含基本值.对象或者函数” //理解对象 ...
- javascript面向对象程序设计
在学习js面向对象编程之前,首先须要知道什么是面向对象.面向对象语言都有类的概念,通过它能够创建具有同样属性和方法的对象.但js并没有类的概念,因此js中的对象和其它语言的对象有所不同. js对象能够 ...
- javascript 面向对象程序设计--深刻理解对象
javascript中,每个对象都是基于一个引用类型创建的,我们可以把ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数. 深刻理解对象 创建自定义对象的最简单方式就 ...
随机推荐
- (转载)MySQL LIKE 用法:搜索匹配字段中的指定内容
(转载)http://www.5idev.com/p-php_mysql_like.shtml MySQL LIKE 语法 LIKE 运算符用于 WHERE 表达式中,以搜索匹配字段中的指定内容,语法 ...
- mysql数据库还原出错ERROR:Unknown command ‘\\’解决手记
使用mysql命令行客户端,使用source导入备份文件,但导入中出错, ERROR: Unknown command ‘\\’. ERROR: Unknown command ‘\”. ERROR: ...
- 通过代码来执行testng.xml
大多数时候,我们都是通过Eclipse IDE上的操作命令来执行testng 框架下的case 运行.那如果我们不想通过这种方式,而是想通过代码调用来实现执行该怎么办?下面是我搜集的两种方式供大家参考 ...
- Java8中Lambda表达式的10个例子
Java8中Lambda表达式的10个例子 例1 用Lambda表达式实现Runnable接口 //Before Java 8: new Thread(new Runnable() { @Overri ...
- 深度学习Matlab DeepLearningToolBox 工具包最常见错误解决办法\
deeplearningtoolbox 下载链接github : https://github.com/rasmusbergpalm/DeepLearnToolbox,只需要解压到matlab当前工 ...
- WebForm Repeater的事件、后天数据展示--2017年1月8日
Repeater的Command操作 1.ItemCommand事件 :在Repeater中所有能触发事件的控件,都会来触发这一个事件 CommandName : 判断点击的是什么按钮,e.Comma ...
- 华为EC169在MAC 10.9.6下的安装方法
[问题描述] 华为EC169 3G上网卡需要在mbp中安装驱动. 华为官网(http://consumer.huawei.com/cn/)直接搜索EC169,会发现最新的驱动也是2009年发布. 下载 ...
- 用ISE14.7引用功能强大的UltraEdit编写Verilog
对于FPGA初学者来说,使用FPGA编译软件所带的编辑器写代码已经完全够用,但随着工程的不断增大,ISE自带的编辑器用起来显得有点力不从心,所以本文中我将为大家分享一款功能强大的编辑软件UltraEd ...
- UVA 10627 - Infinite Race(数论)
UVA 10627 - Infinite Race option=com_onlinejudge&Itemid=8&page=show_problem&category=516 ...
- 使用Partitioner实现输出到多个文件
1.需求 按学生的年龄段,将数据输出到不同的文件.这里我们分为三个年龄段:小于等于20岁.大于20岁小于等于50岁和大于50岁 2.实现 1.编写Partitioner,代码如下 public sta ...