Javascript之对象的继承
继承是面向对象语言一个非常重要的部分。许多OOP语言都支持接口继承和实现继承两种方式。接口继承:继承方法签名;实现继承:继承实际的方法。在ECMAScript中函数是没有签名的,所以也就无法实现接口继承,只能支持实现继承。
在JavaScript中有大概六种继承方式,它们分别是:原型链继承,借用构造函数继承,组合继承,原型式继承,寄生式继承和寄生组合式继承。下面就是对着六种继承方式的详细介绍。
1.原型链
基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。在这里还得补充一下,每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
function BasicType() {
this.property=true;
this.getBasicValue = function(){
return this.property;
};
}
function NewType() {
this.subproperty=false;
}
NewType.prototype = new BasicType();
var test = new NewType();
alert(test.getBasicValue()); //true
由上面可以知道,其本质上是重写了原型对象,代之一个新类型的实例。在通过原型链继承的情况下,要访问一个实例属性时,要经过三个步骤:1搜索实例;2搜索NewType.prototype;3搜索BasicType.prototype,此时才找到方法。如果找不到属性或者方法,会一直向上回溯到末端才会停止。要想确定实例和原型的关系,可以使用instanceof和isPrototypeof()测试,只要是原型链中出现过的原型,都可以说是该原型链所派生实例的原型。还有一点需要注意,通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这时会重写原型链,原型链会被截断。
2借用构造函数继承
其大体思路是,在子类型构造函数的内部调用超类型构造函数。
function BasicType(name) {
this.name=name;
this.color=["red","blue","green"];
}
function NewType() {
BasicType.call(this,"syf");
this.age=23;
}
var test = new NewType(); alert(text.name); //syf
alert(text.age); //23
这种继承实现方式有一种优势就是,可以在子类型构造函数中向超类型构造函数中传递参数,其缺点是不能进行函数复用。
3组合式继承
组合继承就是将原型链和借用构造函数继承模式结合起来,从而具有二者优势的方法。其理念是使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承。
function BasicType(name) {
this.name=name;
this.colors=["red","blue","green"];
}
BasicType.prototype.sayName=function(){
alert(this.name);
}
function NewType(name,age) {
BasicType.call(this,name);
this.age=age;
}
var test = new NewType("syf","23");
test.colors.push("black");
alert(test.colors); //"red,blue,green,black"
alert(test.name); //"syf"
alert(test.age); //
组合式继承避免了原型链和借用构造函数继承方式的缺陷,融合了他们的优点,成为了js中最常用的继承方式。
4原型式继承
原型链继承和原型式继承只有一字之差,但他们的机理还是有所差别的。原型式继承是借助于已有的对象来创建新对象,也就是必须有一个对象可以作为另外一个对象的基础。继承方式函数表达为:
function object (o) {
function F(){}
F.prototype = o;
return new F();
}
我们可以在o的基础上进行修改,来创建特定的对象。直观上来说,其与原型链继承最大的不同之处就是没有使用new操作符。
5寄生式继承
寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来继承对象,最后再返回对象。具体为:
function createAnother ( original ){
var clone = object (original); //通过调用函数创建一个新对象
clone.sayHi=function(){ //以某种方式来增强这个对象
alert("hi");
};
return clone; //返回对象
}
在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。使用寄生式继承来为对象添加函数,函数复用率低。
6寄生组合式继承
上面提到组合式继承,其也是JS里最常用的基础模式。但,由于其会调用两次超类型的构造函数:一次在创建子类型的时候,另一次是在子类型构造函数内部。也就是子类型最终会包含超类型的全部实例属性,但在调用子类型构造函数时会重写这些属性。寄生组合式继承的大致思路为:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。也就是说,不必为了指定子类型的原型而调用超类型的构造函数,我们需要的是超类型原型的一个副本而已。本质上就是,使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。基本模式如下:
function inheritPrototype (subType ,superType){
var prototype = object (superType.prototype); //创建对象,创建超类型原型的一个副本
prototype.constructor = subType; //增强对象,为创建的副本添加constructor属性
subType.prototype = prototype; //指定对象,将新创建的对象赋值给子类型的原型
}
由于寄生组合式继承弥补了组合式继承缺点,所以也被众多开发者认为是最理想的继承方式。
以上就是JS里的六种继承方式的介绍,在编程实践中具体选取哪种方式还要根据当时情况来判定,适合的才是最好的,并一定非得使用组合式继承或者寄生组合式继承来完成继承。
Javascript之对象的继承的更多相关文章
- 关于JavaScript中对象的继承实现的学习总结
一.原型链 JavaScript 中原型链是实现继承的主要方法.其主要的思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.实现原型链有一种基本模式,其代码如下. function Super ...
- Javascript实现对象的继承
在Java和C#中,你可以简单的理解class是一个模子,对象就是被这个模子压出来的一批一批月饼.压个啥样,就得是个啥样,不能随便动,动一动就坏了.而在Javascript中,没有模子,月饼被换成了面 ...
- JavaScript教程——对象的继承
面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过“类”(class) ...
- javascript中对象函数继承的概念
什么是函数对象?这个对象既是通常意义上的对象,又可以加上括号直接执行的函数. 产生函数对象的方式有两种:1.通过function关键字产生:var fn = function(){};2.实例化Fun ...
- javascript实现对象的继承的方式
在JavaScript将原型链作为实现继承的主要方法.基本原理是利用原型让一个subType引用superType的属性和方法 推荐链接 http://www.jb51.net/article/204 ...
- javascript中的对象之间继承关系
相信每个学习过其他语言的同学再去学习JavaScript时就会感觉到诸多的不适应,这真是一个颠覆我们以前的编程思想的一门语言,先不要说它的各种数据类型以及表达式的不同了,最让我们头疼,恐怕就是面向对象 ...
- #JavaScript对象与继承
JavaScript对象与继承 JavaScript是我在C语言之后接触的第二门编程语言,大一暑假的时候在图书馆找了一本中国人写的JavaScript程序设计来看.那个时候在编程方面几乎还是小白,再加 ...
- Javascript学习6 - 类、对象、继承
原文:Javascript学习6 - 类.对象.继承 Javasciprt并不像C++一样支持真正的类,也不是用class关键字来定义类.Javascript定义类也是使用function关键字来完成 ...
- JavaScript 面向对象编程(三):非构造函数对象的继承
JavaScript 面向对象编程(三):非构造函数对象的继承 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese ...
随机推荐
- 09.VMWare虚拟机copy后网卡不是eth0解决办法
0.如果VM虚拟机已经复制了,网卡已经不是eth0了,看下面1--->步骤,如果还没复制将要复制,只看1就行 点击I copy it.这时虚拟机会在开机时检查是否次网卡无力地址已经存在, ...
- kaili 2.0 虚拟机修改ip
第一步:将虚拟机设置为桥接状态,并勾选上复制物理网络连接状态
- CUBRID学习笔记 14 删除主键错误
发生这样的问题.其实和别的数据库基本原因差不多. 就是外键冲突. 看看有没有外键引用这个表的主键. 然后删除外键. 就可以了 SELECT class_name FROM db_index WHER ...
- 简单几步配置gitlab
简单几步配置gitlab 之前配置gitlab需要很多步骤,要装apache2.ruby.tomcat.mysql等一片东西.有没有更简单的方式呢?现在可以借助bitnami,简化了很多. 可以参考v ...
- hdu2037-----------贪心, 活动安排问题
http://acm.hdu.edu.cn/showproblem.php?pid=2037(简单贪心-----活动安排) #include<iostream> #include<a ...
- C#正则表达式编程(一):C#中有关正则的类
正则表达式是一门灵活性非常强的语言,匹配同样的字符串可能在不同的开发人员那里会得到不同的结果,在平常的时候也是用的时候看看相关资料,不用的时候就丢在脑后了,尽管在处理大部分情况下都能迅速处理,但是处理 ...
- yii CDbCriteria 类的总结
在编程中,我们通常会需要查询些东西,但是通过查询的时候,yii有个集成的类--- CDbCriteria():通过该类,我们可以更加便捷的调用数据. 参考网址:http://www.cnblogs.c ...
- 强制性签出被人没有签入的文件(在.net开发vs中)
灵感,是天才的女神.她并不步履蹒跚地走过,而是在空中像乌鸦那么警觉地飞过的,她没有什么剽带给诗人抓握,她的头是一团烈火,她溜得快,像那些白里带红的鹤,教猎人见了无可奈何.——巴尔扎克(上海网站建设) ...
- redis数据库选择-select
1.关于redis的select命令用法: SELECT index 切换到指定的数据库,数据库索引号 index 用数字值指定,以 0 作为起始索引值. 默认使用 0 号数据库. 可用版本: > ...
- adb_亮屏
来自:http://justonlypiano.blogspot.tw/2013/08/adbandroidandroid-phone-screen-off-via.html 更多内容请查看:http ...