我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧!

上回我们说到组合继承在使用构造函数继承时继承了一遍父类构造函数,在实现子类原型的类式继承时又调用了一遍父类构造函数。因此父类构造函数调用了两遍,并不算最优的继承方式,下面我们再来介绍更好的方式。

原型式继承

首先我们声明一个对象

function proObject(o){
//声明一个过渡函数对象
function Obj(){}
//过渡对象的原型继承父对象
Obj.prototype=o;
//返回过渡对象的一个实例,该实例的原型继承了父对象
return new Obj();
}

是不是觉得这种方式和我们之前讲到的类式继承很相似,的确原型式继承是对类式继承的一个封装,其中的过渡对象就相当于类式继承中的子类,过渡的意义主要是想返回一个新的实例化对象。

Object.create()方法就是原型式继承。

那么类式继承的那些缺点是否也会在原型式继承中提现出来呢?答案是肯定的,我们来看看下面的例子

var Students={
admissionTime:"2017",
hobby:["唱歌","画画"]
};
var student1=proObject(Students);
student1.admissionTime="2016";
student1.hobby.push("游泳"); var student2=proObject(Students);
student2.admissionTime="2015";
student2.hobby.push("看书");

接着我们把结果打印出来看看

console.log(student1.admissionTime);//2016
console.log(student1.hobby);//["唱歌","画画","游泳","看书"] console.log(student2.admissionTime);//2015
console.log(student2.hobby);//["唱歌","画画","游泳","看书"] console.log(Students.admissionTime);//2017
console.log(Students.hobby);//["唱歌","画画","游泳","看书"]

还是和之前的类式继承一样值类型的属性被复制,引用类型的属性被共用了。所以在原型式继承的基础上做了些增强出现了下面的继承方式。

寄生式继承

寄生式继承其实就是对原型式继承的第二次封装,并且在第二次封装过程中对继承的对象进行了拓展,这样新创建的对象不仅仅有父类中的睡醒和方法,而且还添加了新的属性和方法。

首先我们先声明基类对象

var Students={};
function CreateStu(obj){
//通过原型式继承方式创建新对象
var stu=proObject(obj);
//扩展新对象
stu.getAdmissionTime=function(){
console.log(stu.admissionTime);
};
//返回拓展后的新对象
return stu;
}
var student1=CreateStu(Students);
student1.admissionTime="2016";
student1.hobby.push("游泳"); var student2=CreateStu(Students);
student2.admissionTime="2015";
student2.hobby.push("看书");

接着我们把结果打印出来看看

student1.getAdmissionTime();//2016
console.log(student1.hobby);//["唱歌","画画","游泳","看书"] student2.getAdmissionTime();//2015
console.log(student2.hobby);//["唱歌","画画","游泳","看书"]

这种类型的继承就跟他的名字一样,像寄生虫一样寄托于某个对象内部生长,当然这种思想是为了我们接下来的继承模式的实现

寄生组合式继承

我们之前讲到的组合式继承,是将类式继承和构造函数继承组合使用,但这种方式有个问题,父类构造函数调用了两遍而且子类不是父类的实例,子类的原型才是父类的实例,所以才有了我们现在讲到的寄生组合式继承。

那么寄生组合式继承又是哪两种模式的组合呢?

由名字我们可以看出,寄生当然是指寄生式继承而寄生式继承又依托于原型式继承,我们之前讲到原型式继承和类式继承相似,所以另一种继承模式就是构造函数继承。

寄生式继承有些特殊,他处理的不是对象,而是类的原型。

下面我们来看一下具体的实现步骤

function parasiticType(ParentClass,ChildClass){
//复制一份父类的原型保存在变量中
var parent=proObject(ParentClass.prototype);
//修正因为重写子类原型导致子类的constructor属性被修改
parent.constructor=ChildClass;
//设置子类的原型
ChildClass.prototype=parent;
}

组合式继承中,通过构造函数继承的属性和方法是没有问题的,所以这里我们主要探究通过寄生式继承重新继承父类的原型。

我们需要继承的仅仅是父类的原型,不再需要调用父类的构造函数。

所以我们需要的其实就只有父类原型对象的副本,而这个副本我们可以通过原型式继承得到,但是我们直接赋值给子类会有问题的,因为对父类原型对象复制得到的复制对象parent中的constructor指向的不是ChildClass子类对象,

因此在寄生式继承中,我们要对复制对象parent做一次增强,修复器constructor属性指向不正确的问题,最后我们将得到的复制对象P赋值给子类的原型,这样子类的原型就继承了类的原型并且没有执行父类的构造函数。

constructor是一个属性,当创建一个函数或者对象时都会为其创建一个原型对象prototype,在prototype对象中,又会想函数中创建this一样创建一个constructor属性,那么constructor属性指向的就是拥有整个原型对象的函数或者对象。

下面我们来看一下具体实现的步骤

首先我们定义一个父类

function ParentClass(id){
//引用类型的公有属性
this.parentValue=['C#','JAVA','PHP'];
//值类型公有属性
this.id=id;
}

接着我们声明父类的原型方法

ParentClass.prototype.getParentValue=function(){
console.log(this.parentValue);
}

下面我们声明子类

function ChildClass(id,childValue){
//构造函数式继承父类
ParentClass.call(this,id);
//子类新增属性
this.childValue=childValue;
}

寄生式继承父类原型

parasiticType(ParentClass,ChildClass);

子类新增原型方法

ChildClass.prototype.getChildValue=function(){
console.log(this.time);
}

接着我们创建两个测试方法

var test1=new ChildClass(1,"张三");
var test2=new ChildClass(2,"李四");

接着我们来测试一下

test1.parentValue.push("C++");
console.log(test1.parentValue);//["C#", "JAVA", "PHP", "C++"]
console.log(test2.parentValue);//["C#", "JAVA", "PHP"]
test1.getParentValue();//["C#", "JAVA", "PHP", "C++"]
test1.getChildValue();//张三
test2.getParentValue();//["C#", "JAVA", "PHP"]
test2.getChildValue();//李四

这里我们要注意一点,子类再想添加原型方法必须通过prototype对象,通过点语法的形式一个一个添加方法,否则直接赋予对象就会覆盖掉从父类原型继承的对象。

到这里我们的继承大致就介绍完了,下面我们开始介绍如何使用javascript实现多态

多态

在面向对象的语言中,我们通过方法重载来实现多态,在javascript中我们可以对传入的参数做判断实现多种调用方式从而达到实现多态的效果。

首先我们定义一个方法

function polymorphism(){
//获取参数
var argument=arguments;
//获取参数长度
var len=argument.length;
switch(len){
//如果没有参数
case 0:
return 0;
//如果只有一个参数
case 1:
return 1;
//如果有两个参数
case 2:
return 2;
}
}

我们来试一试

console.log(polymorphism());//0
console.log(polymorphism(1));//1
console.log(polymorphism(1,2));//2

这样我们就很简单的实现了多态的效果,好了这就是本次分享的全部内容,下一章我们开始正式进入javascript设计模式。

也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~

好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

再起航,我的学习笔记之JavaScript设计模式04的更多相关文章

  1. 再起航,我的学习笔记之JavaScript设计模式02

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

  2. 再起航,我的学习笔记之JavaScript设计模式01

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 在通 ...

  3. 再起航,我的学习笔记之JavaScript设计模式03

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 上一 ...

  4. 再起航,我的学习笔记之JavaScript设计模式05(简单工程模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  5. 再起航,我的学习笔记之JavaScript设计模式06(工厂方法模式)

    上一次已经给大家介绍了简单工厂模式,相信大家对创建型设计模式有了初步的了解,本次我将给大家介绍的是工厂方法模式. 工厂方法模式 工厂方法模式(Factory Method):通过对产品类的抽象使其创建 ...

  6. 再起航,我的学习笔记之JavaScript设计模式05(简单工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  7. 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...

  8. 再起航,我的学习笔记之JavaScript设计模式08(建造者模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  9. 再起航,我的学习笔记之JavaScript设计模式09(原型模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

随机推荐

  1. flask简单web应用

    推荐一个学习python的网站,个人觉得在这里面收获挺大的,希望对后来学习flask的小伙伴们有帮助.http://www.pythondoc.com/ 用flask框架实现第一个web应用 首先需要 ...

  2. 开源Inno Setup官网下载、安装、打包教程(官网安装向导中文语言包)

    安装Inno Setup篇 1.搜索Inno Setup 2.下载Inno Setup 3.选择下载最新 innosetup-5.5.9-unicode.exe 版本(innosetup-5.5.9. ...

  3. 【原】无脑操作:eclipse + maven搭建SSM框架

    网上看到一些Spring + Spring MVC + MyBatis框架的搭建教程,不是很详细或是时间久远了,自己动手整一个简单无脑的! 0.系统环境 1)Windows 10 企业版 2)JDK ...

  4. [leetcode-521-Longest Uncommon Subsequence I]

    Given a group of two strings, you need to find the longest uncommon subsequence of this group of two ...

  5. 【Android Developers Training】 6. 配置Action Bar

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. redis可视化工具redisClient

    下载连接:百度网盘 直接解压就可以用了

  7. Vim按Esc后光标左移问题的解决

    参考了这篇文章http://vim.wikia.com/wiki/Prevent_escape_from_moving_the_cursor_one_character_to_the_left 在Vi ...

  8. 【总算解决了】A network-related or instance-specific error occurred while establishing a connection to SQL Server

    给别人做的网站莫名其妙连接不上数据库.百度了好多,总算知道自己的错在哪了. 报 "A network-related or instance-specific error occurred  ...

  9. 外部世界如何访问容器? - 每天5分钟玩转 Docker 容器技术(37)

    上节我们学习了容器如何访问外部网络,今天讨论另一个方向:外部网络如何访问到容器? 答案是:端口映射. docker 可将容器对外提供服务的端口映射到 host 的某个端口,外网通过该端口访问容器.容器 ...

  10. MySQL(三)--函数与谓词

    前文已有涉及,这里作为总结重新整理一下. 一.函数 1.算术函数 NUMERIC 是大多数 DBMS 都支持的一种数据类型,通过 NUMBERIC ( 全体位数, 小数位数 ) 的形式来指定数值的大小 ...