实现继承的方法:

一,原型链:利用原型让一个引用类型继承另一个引用类型的属性和方法

function SuperType(){
this.property=true;
} SuperType.prototype.getSuperValue=function(){
return this.property;
};
function SubType(){ this.subproperty=false;
}
//继承了SuperType
SubType.prototype=new SuperType();
SubType.prototype.getSubValue=function(){
return this.subproperty; }
var instance=new SubType();
alert(instance.getSuperValue()); //true

注意问题:

a:所有引用类型默认都继承了Object,也是通过原型链实现的,所有函数的默认原型都是Object的实例。

alert(instance instanceof Object);  //true

b:确定原型和实例之间的关系,可以用instanceof操作符和isPrototypeOf()方法。

实例与原型链中出现过的构造函数都会返回true。

alert(instance instanceof SubType);  //true 

原型链中出现过的原型,都可以说是原型链派生的实例的原型,返回true。

alert(SubType.prototype.isPrototypeOf(instance));  //true

c:给原型添加方法的代码一定要放在替换原型的语句之后。

d:通过原型链实现继承时不能使用对象字面量创建原型的方法,这样会重写原型链,之前的原型链被切断,SubType和SuperType之间没有关系了。

e:原型链的问题:每个实例都会共享属性,子类型不能向超类型中传参

优点:实例的方法可以共享

缺点:所有实例的属性共享

二,借用构造函数:在子类的构造函数内部调用超类型构造函数

function SuperType(){
this.colors=["red","blue","green"];//该数组就是引用类型值
}
function SubType(){
  //继承了SuperType
   SuperType.call(this);//SuperType.call(this)的意思就是使用SuperType 对象代替this对象,那么Subtype中不就有SuperType的所有属性和方法了,instance1对象就能够直接调用SuperType的方法以及属性了
}
var instance1=new SubType();
instance1.colors.push("black");
alert(instance1.colors); //red,blue,green,black var instance2=new SubType();
alert(instance2.colors);//red,blue,green

a:可以传递参数

b:借用构造函数问题:方法都在构造函数中定义,因此所有函数无法复用

优点:解决了原型链实现继承属性共享的问题,可以传递参数

缺点:函数无法复用,每个实例的方法都不相同

三,组合继承:将原型链和借用构造函数的技术组合到一块,扬长补短,思想:使用原型链对原型属性和方法的继承,使用借用构造函数实现对实例属性的继承。

function SuperType(name){
this.colors=["red","green","blue"];
this.name=name;
}
//用原生链的方式将方法写在外面,让每个实例使用相同的方法
SuperType.prototype.sayName=function(){
alert(this.name);
};
function SubType(name,age){
//第二次调用SuperType()
SuperType.call(this,name); //让每个实例分别拥有自己的属性
this.age=age;
}
//继承方法
SubType.prototype=new SuperType(); //第一次调用SuperType()
//弥补因重写原型而失去的默认的constructor属性
SubType.prototype.constructor=SubType;
SubType.prototype.sayAge=function(){
alert(this.age);
}; var instance1=new SubType("jane",29);
instance1.colors.push("black");
alert(instance1.colors); //red,green,blue,black
instance1.sayName(); //jane
instance1.sayAge(); // var instance2=new SubType("tom",30);
alert(instance2.colors);//red,green,blue
instance2.sayName(); //tom
instance2.sayAge(); // alert(instance1.sayName==instance2.sayName); //true
alert(SubType.prototype.constructor==SubType);//true

优点:最常用的继承模式,解决了借用构造函数,函数不能复用的问题,以及原型链属性共享,以及不能传参的问题

缺点:如代码中所说,调用了两次超类型构造函数,如果删除instance2的colors属性,依然会返回red,green,blue,这样就无法删除colors属性

delete instance2.colors;
alert(instance2.colors);//red,green,blue

四,原型式继承:基于已有的对象创建新对象

Object.create()方法实现原型式继承:

//传入一个参数的情况下,对象名
var person={
name:"jane",
friends:["tom","nike","van"]
}; var anotherPerson=Object.create(person);
anotherPerson.name="greg";
anotherPerson.friends.push("rob"); var yetAnotherPerson=Object.create(person);
yetAnotherPerson.name="linda";
yetAnotherPerson.friends.push("barbie"); alert(person.friends); //tom,nike,van,rob,barbie*
//Object.create()方法传入两个参数,第一个参数,对象名,第二个参数:属性都是通过自己的描述符定义的。
var person={
name:"jane",
friends:["tom","nike","van"]
};
var anotherPerson=Object.create(person,
{
    //以这种方式指定的任何属性都会覆盖原型对象上的同名属性。
name:{
value:"greg"
}
}
); alert(anotherPerson.name); //greg

优点:不用再创建自定义的类型了

缺点:引用类型值的属性都会共享相应的值

五,寄生式继承:封装继承过程的函数

//createAnother函数接收了一个参数,也就是将要作为新对象基础的对象。
function createAnother(original){
//把original对象传递给Object函数,将返回的结果赋给clone
var clone=Object(original);
//再为clone对象添加一个方法
clone.sayHi=function(){
alert("hi");
};
return clone;//返回这个对象
} var person={
name:"jane",
friends:["tom","nike","van"]
}; var anotherPerson=createAnother(person);
anotherPerson.sayHi();//hi anotherPerson具有Person不具有的方法sayHi()

优点:为对象添加函数

缺点:函数无法复用

六,寄生组合式继承:使用寄生式继承超类型的原型,再将结果返回给子类型的原型。

function inheritPrototype(SubType,SuperType){
var prototype=Object(SuperType.prototype);//创建对象
prototype.constructor=SubType; //弥补因重写原型而失去的默认的constructor属性
SubType.prototype=prototype;//指定对象
}
function SuperType(name){
this.name=name;
this.colors=["red","green","blue"];
}
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 instence=new SubType("jane",29);
instence.sayName();
instence.sayAge();

优点:解决了组合继承的两次调用超类型构造函数问题

整理js继承的更多相关文章

  1. JS继承的从入门到理解

    开场白 大三下学期结束时候,一个人跑到帝都来参加各厂的面试,免不了的面试过程中经常被问到的问题就是JS中如何实现继承,当时的自己也是背熟了实现继承的各种方法,回过头来想想却不知道__proto__是什 ...

  2. 一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends

    说实在话,以前我只需要知道"寄生组合继承"是最好的,有个祖传代码模版用就行.最近因为一些事情,几个星期以来一直心心念念想整理出来.本文以<JavaScript高级程序设计&g ...

  3. js继承

    js继承有5种实现方式: 继承第一种方式:对象冒充 function Parent(username){ this.username = username; this.hello = function ...

  4. js继承之call,apply和prototype随谈

    在js中,call,apply和prototype都可以实现对象的继承,下面我们看一个例子: function FatherObj1() { this.sayhello = "I am jo ...

  5. js继承精益求精之寄生式组合继承

    一.混合/组合继承的不足 上一篇JS继承终于混合继承,认真思考一下,发现其还是有不足之处的: 空间上的冗余:在使用原型链的方法继承父类的原型属性(Animal.prototype)的同时,也在子类的原 ...

  6. 老生常谈--Js继承小结

    一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.net/stoy ...

  7. Js继承小结

    Js继承小结 一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.n ...

  8. js继承实现

    JS实现继承可以分为:对象冒充和原型链继承 其中对象冒充又包括:临时变量,call 和 apply 临时变量方法: function Person(name,sex){ this.name = nam ...

  9. js继承之借用构造函数继承

    我的上一篇文章介绍了,原型链继承模式.但是单纯的原型链模式并不能很好地实现继承. 一.原型链的缺点 1.1 单纯的原型链继承最大的一个缺点,来自于原型中包含引用类型的值. 本来,我们没有通过原型链实现 ...

随机推荐

  1. windows下adb(android调试桥)基本命令(持续更新。。。)

    前言:刚开始学习android(坚持每天1篇笔记哈^_^),比较实用的命令是adb,所以就先学习这些,主要用真机调试,模拟器用的是genymotion,所以emulator暂时不大需要哈,可以后续再补 ...

  2. (原)vs2013静态及动态链接opencv3.0的库

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5477551.html 静态链接步骤如下: 1. 在“通用配置”-“VC++目录”-“包含目录”中添加: ...

  3. [Leetcode] Two Sum (C++)

    我在Github上新建了一个解答Leetcode问题的Project, 大家可以参考, 目前是Java 为主,里面有leetcode上的题目,解答,还有一些基本的单元测试,方便大家起步. 题目: Gi ...

  4. Maven 学习笔记

    1. Maven 工具的意义: 从事软件开发,无论什么样的项目,什么样的技术,都要经历:编码.测试.打包.发布等几个特定过程,而这些过程在软件开发周期中都是重复的.繁琐的.Maven的出现是为了将开发 ...

  5. URL锚点定位

    我们都知道<a>标签中的url属性有三种值: 绝对 URL - 指向另一个站点(比如 href="http://www.example.com/index.htm") ...

  6. python运维开发(二十五)---cmdb开发

    内容目录: 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infr ...

  7. shell练习--用户下载交互检测

    #!/bin/bash #By spinestars #-- read -p "请输入下载目录路径" down_dir read -p "请输入网址路径" ur ...

  8. Linux系统编程(5)——文件与IO之mmap函数

    mmap系统调用它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作.而Posix或系统V的共享内存IPC则纯粹用于共享目的,mmap()实现共享内存也是其主要应用之一. ...

  9. 【转】Android虚拟平台的编译和整合

    原文网址:http://blog.csdn.net/rickleaf/article/details/6369065 概要 Android从2008年开始到本文写的2011年,短短三年的时间里成为手机 ...

  10. iptables or netfilter

    netfilter 内部有三个表:filter .nat .mangle 每个表又有不同的操作链: 1.在filter这个防火墙功能的表中有三个chain:INPUT.FORWARD.OUTPUT. ...