再起航,我的学习笔记之JavaScript设计模式04
我的学习笔记是根据我的学习情况来定期更新的,预计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的更多相关文章
- 再起航,我的学习笔记之JavaScript设计模式02
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...
- 再起航,我的学习笔记之JavaScript设计模式01
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 在通 ...
- 再起航,我的学习笔记之JavaScript设计模式03
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 上一 ...
- 再起航,我的学习笔记之JavaScript设计模式05(简单工程模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...
- 再起航,我的学习笔记之JavaScript设计模式06(工厂方法模式)
上一次已经给大家介绍了简单工厂模式,相信大家对创建型设计模式有了初步的了解,本次我将给大家介绍的是工厂方法模式. 工厂方法模式 工厂方法模式(Factory Method):通过对产品类的抽象使其创建 ...
- 再起航,我的学习笔记之JavaScript设计模式05(简单工厂模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...
- 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...
- 再起航,我的学习笔记之JavaScript设计模式08(建造者模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...
- 再起航,我的学习笔记之JavaScript设计模式09(原型模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...
随机推荐
- VR虚拟现实技术在教育领域的前景展望
VR虚拟现实技术在教育领域的前景展望 VR虚拟现实技术能迅速火起来,是基于它突破了人们对三维空间在时间与地域上的感知限制,以及市场需求愿景的升级.此技术可广泛地应用到城市规划.室内设计.工业仿真.古迹 ...
- PHP扩展开发-1
开发环境信息 1.基本环境信息如下: [root@localhost lib]# cat /etc/os-release NAME="CentOS Linux" VERSION=& ...
- 从Owin到System.Web.Http.Owin的HttpMessageHandlerAdapter看适配器模式
.mytitle { background: #2B6695; color: white; font-family: "微软雅黑", "宋体", "黑 ...
- 限制input[type=number]的输入位数策略整理
当我们使用类型number的input输入框的时候,我们可能需要限制输入的位数,这个时候通常会想到maxlength,但是maxlength是在number类型的时候是不支持的,下面是一些解决这种问题 ...
- 自己动手写一个自动登录脚本gg
1.下载一个sshpass工具 2.安装sshpass,安装到tools文件夹 3.把tools文件夹的路径加入到/etc/bashrc vim /etc/bashrc 最后一行 : expor ...
- [leetcode-506-Relative Ranks]
Given scores of N athletes, find their relative ranks and the people with the top three highest scor ...
- html路径问题
1.绝对路径 绝对路径是指文件在硬盘上真正存在的路径.例如"bg.jpg"这个图片是存放在硬盘的"E:\book\网页布局代码\第2章"目录下,那么 ...
- Ionic Demo 解析
Ionic Demo 解析 index.html 解析 1.引入所需要的类库 <link rel="manifest" href="manifest.json&qu ...
- 读书共享 Primer Plus C-part 7
第十章 数组和指针 1.关于二维数组跟指针 #include<stdio.h> int main() { ][]={{,,,},{,,,},{,,,}}; ; ;i< ;i++) ...
- ubuntu主机名修改
1.查看主机名 在Ubuntu系统中,快速查看主机名有多种方法: 其一,打开一个GNOME终端窗口,在命令提示符中可以看到主机名,主机名通常位于"@"符号后: 其二,在终端窗口中输 ...