js知识梳理4.继承的模式探究
写在前面
注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者。有发现什么问题的,欢迎留言指出。
1.原型链
将原型链作为实现继承的方法,基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法:
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();
console.log(instance.getSuperValue());//true
原型链实现继承的问题:①问题来自包含引用类型值的原型,因为原来的实例属性变成现在的原型属性,会被共享,②在创建子类时,不能向超类型的构造函数中传递参数。
function SuperType() {
this.colors = ["red","blue","green"];
}
function SubType() {}
//继承了SuperType
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors);//["red", "blue", "green", "black"]
var instance2 = new SubType();
console.log(instance2.colors);//["red", "blue", "green", "black"]
2.借用构造函数
即是在子类型构造函数的内部调用超类型构造函数(还可以传递参数):
function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
function SubType() {
SuperType.call(this,'jaychou');
}
var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors);//["red", "blue", "green", "black"]
console.log(instance1.name);//jaychou
var instance2 = new SubType();
console.log(instance2.colors);//["red", "blue", "green"]
console.log(instance2.name);//jaychou
借用构造函数的问题:方法都在构造函数中定义,没有进行函数复用。而且在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。
3.组合继承
即使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性:
function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function () {
console.log(this.name);
}
function SubType(name,age) {
//继承实例属性
SuperType.call(this,name);
this.age = age;
}
//继承原型中的方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function () {
console.log(this.age);
}
var instance1 = new SubType('jaychou',34);
instance1.colors.push("black");
console.log(instance1.colors);//["red", "blue", "green", "black"]
instance1.sayName();//jaychou
instance1.sayAge();//34
var instance2 = new SubType('xiaoming',15);
console.log(instance2.colors);//["red", "blue", "green"]
instance2.sayName();//xiaoming
instance2.sayAge();//15
4.原型式继承
没有使用严格意义上的构造函数,借助原型可以基于已有的对象创建新对象的特点。同时还不必因此创建自定义类型:
function inherit(p) {
if(p==null) throw TypeError();
if(Object.create) return Object.create(p);
var t = typeof p;
if(t !== "object" && t !== "funtion") throw TypeError();
function f() {};
f.prototype = p;
return new f();
}
好处:简单直接方便,只是简单地想一个对象与另一个对象保持类似的情况下,原型式继承是很不错的做法。注意点:包含引用类型值的属性始终都会共享相应的值,就像使用原型模式一样,如:
var person = {
name:'jaychou',
friends:[1,2]
}
var anotherP = inherit(person);
anotherP.friends.push(3);
console.log(person.friends);//[1, 2, 3]
anotherP.name = "xiaoming";
console.log(anotherP.name);//xiaoming
console.log(person.name);//jaychou
所以从本质上讲,原型式继承就是对传过来的对象执行了一次浅复制。
5.寄生式继承
即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象(接上):
function createAnother(original) {
var clone = inherit(original);
clone.sayHi = function () {
console.log("hi");
}
return clone;
}
var person = {
name:'jaychou',
friends:[1,2]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();
在例子里给传进来的对象增加了方法sayHi,增强了对象。在主要考虑对象而不是自定义类型和构造函数的情况下,这个模式也不错。缺点:不能做到函数复用而降低效率了。
6.寄生组合式继承
组合继承的问题就是调用了两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。解决方案就是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型:
//寄生组合式继承
function inheritPrototype(subType, superType) {
var prototype = inherit(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function () {
console.log(this.name);
}
function SubType(name,age) {
//借用超类型的构造函数继承了超类型的实例属性
SuperType.call(this,name);
this.age = age;
}
//寄生式继承了超类型的原型方法
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function () {
console.log(this.age);
}
var instance1 = new SubType("jaychou",34);
instance1.sayName();//jaychou
instance1.sayAge();//34
console.log(SuperType.prototype.isPrototypeOf(instance1));//true
console.log(instance1 instanceof SuperType);//true
好处:①只调用了一处SuperType构造函数,②避免了在SubType.prototype上面创建不必要的、多余的属性。综上,寄生组合式继承是继承的最理想方式。
js知识梳理4.继承的模式探究的更多相关文章
- js知识梳理3:创建对象的模式探究
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- js知识梳理5:关于函数的要点梳理(1)
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- js知识梳理6:关于函数的要点梳理(2)(作用域链和闭包)
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- js知识梳理2:对象属性的操作
1.属性的查询和设置 ①基本语法 这个简单,可以通过点(.)或方括号([])运算来获取属性的值,注意点运算符后的标识符不能是保留字,方括号内的表达式必须返回字符串或返回一个可以转换成字符串的值. va ...
- js知识梳理1:理解对象的属性特性
1.数据属性 数据属性的4个特性: Configurable:①表示能否通过delete删除属性从而重新定义,②能否修改属性的特性,③能否把属性修改为访问器属性.对象直接量里默认值true. Enum ...
- JS知识梳理--图表
- Vue.js 2.x API 知识梳理(一) 全局配置
Vue.js 2.x API 知识梳理(一) 全局配置 Vue.config是一个对象,包含Vue的全局配置.可以在启动应用之前修改指定属性. 这里不是指的@vue/cli的vue.config.js ...
- js基础知识梳理(最简版)
基础的JavaScript知识,只放XMind截图.小白 JS01 JS02 JS03 最基础的js知识--!
- solr DIH 知识梳理
solr DIH 知识梳理 web.xml中listener配置 <listener> <listener-class>org.apache.solr.handler.data ...
随机推荐
- OSPF协议原理及配置3-邻居关系的建立
OSPF协议原理及配置3-邻居关系的建立 OSPF协议的邻居关系是通过交换Hello报文建立的,所以我们先对OSPF的报文的种类,及Hello报文的结构做一了解. 1 OSPF协议有5种协议报文( ...
- Applied Social Network Analysis in Python 相关笔记3
如果是option2的话,答案选A. 这里节点s,从左边的选择,节点t从右边选择. 这里计算还是用以前的值,不用更新过的值.
- 『现学现忘』Docker基础 — 25、Docker镜像讲解
目录 1.镜像是什么 2.Docker镜像获取的方式 3.Docker镜像加载原理 (1)UnionFS(联合文件系统) (2)Docker镜像加载原理 1.镜像是什么 镜像是一种轻量级.可执行的独立 ...
- CF498B题解
咋黑色啊,这不是看到数据范围就去想 \(O(nT)\) 的做法吗? 然后仔细想想最靠谱的就是 DP. 设 \(dp[n][T]\) 表示听完第 \(n\) 首歌,总共听了 \(T\) 秒. 很明显有 ...
- http请求中的三种参数类型
1.URL参数:实际就是querry string的方式,参数拼接在url之后以?隔开,参数之间以&连接. 优点:简单,页面跳转比较快. 缺点:1.基于浏览器对urk长度有限制,不能超过204 ...
- 论文翻译:2021_论文翻译:2018_F-T-LSTM based Complex Network for Joint Acoustic Echo Cancellation and Speech Enhancement
论文地址:https://arxiv.53yu.com/abs/2106.07577 基于 F-T-LSTM 复杂网络的联合声学回声消除和语音增强 摘要 随着对音频通信和在线会议的需求日益增加,在包括 ...
- Python tkinter库将matplotlib图表显示在GUI窗口上,并实时更新刷新数据
代码 1 ''' 2 使用matplotlib创建图表,并显示在tk窗口 3 ''' 4 import matplotlib.pyplot as plt 5 from matplotlib.pylab ...
- 四旋翼中的PID调节方法 | betaflight固件如何调节PID
roll横滚,pitch俯仰,yaw航向 一.PID的作用概述 1.P产生响应速度和力度,是I和D的基础 过小响应慢(虽然无震荡) 过大会产生振荡且不断发散 2.D抑制过冲和振荡,抵抗外界的突发干扰, ...
- Github使用指南(学习中随时更新)
注册好一个账号后先创建一个仓库 点击"Create repository"创建一个版本库 填好带*号的必填项,选择是要公开仓库还是私人使用,勾选自动添加README选项 READM ...
- zookeeper有几种部署模式? zookeeper 怎么保证主从节点的状态同步?
一.zookeeper的三种部署模式 Zookeeper 有三种部署模式分别是单机模式.伪集群模式.集群模式.这三种模式在不同的场景下使用: 单机部署:一般用来检验 Zookeeper 基础功能,熟悉 ...