javascript中继承方式及优缺点(一)
分别介绍原型链继承、call/apply继承(借用构造函数继承)、组合继承、原型式继承、寄生式继承、寄生组合式继承
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();
alert(instance.getSuperValue());//true
简单的原型链分析

使用原型创建对象会存在多个实例对引用类型的操作会被篡改的问题,在上面同样存在这个问题,如下:
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){}
SubType.prototype = new 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,black"
两个实例对象instance1和instance2的colors属性指向相同,改变一个会影响另一个实例的属性
缺陷:
(1)原型链继承多个实例的引用类型属性指向相同,存在篡改的可能
(2)不能传递参数
2. 借用构造函数继承
核心:使用父类的构造函数来增强子类实例,等同于复制父类的实例给子类(不使用原型)
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
function SubType(name, age){
// 继承自SuperType
SuperType.call(this, name);
this.age = age;
}
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"
alert(instance1.name); // "Nicholas"
alert(instance1.age); // 29
借用构造函数继承的核心就在于SuperType.call(this, name),“借调”了SuperType构造函数,这样,SubType的每个实例都会将SuperType中的属性复制一份
缺陷:
(1)只能继承父类的实例属性和方法,不能继承原型属性/方法
(2)无法实现复用,每个子类都有父类实例函数的副本,影响性能
3. 组合继承
核心:结合原型链继承和构造函数继承通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承,这样,既通过在原型上定义方法实现了函数复用,又能保证每个实例都有它自己的属性
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(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(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
图解:

缺陷:
父类中的实例属性和方法既存在于子类的实例中,又存在于子类的原型中,不过仅是内存占用,因此,在使用子类创建实例对象时,其原型中会存在两份相同的属性/方法
这个方法是javascript中最常用的继承模式
4. 原型式继承
核心:直接将某个对象直接赋值给构造函数的原型
function object(obj){
function F(){}
F.prototype = obj;
return new F();
}
object()对传入其中的对象执行了一次浅复制,将F的原型直接指向传入的对象
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
缺点:
(1)原型链继承多个实例的引用类型属性指向相同,存在篡改的可能
(2)无法传递参数
另外,ES5中存在Object.create()的方法,能够代替上面的object方法
5. 寄生式继承
核心:在原型式继承的基础上,增强对象,返回构造函数
function createAnother(original){
varclone=object(original); // 过调用函数创建一个新对象
clone.sayHi = function(){ // 以某种方式增强这个对象
alert("hi");
};
return clone; // 返回对象
}
函数的主要作用是为构造函数新增属性和方法,以增强函数
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"
缺点:
(1)原型链继承多个实例的引用类型属性指向相同,存在篡改的可能
(2)无法传递参数
6. 寄生组合式继承
核心:结合借用构造函数传递参数和寄生模式实现继承
function inheritPrototype(subType, superType){
var prototype = Object.create(superType.prototype); //创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 指定对象
}
// 父类初始化实例属性和原型属性
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
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 instance1 = new SubType("xyc", 23);
var instance2 = new SubType("lxy", 23);
instance1.colors.push("2"); // ["red", "blue", "green", "2"]
instance1.colors.push("3"); // ["red", "blue", "green", "3"]
图解:

寄生组合继承集合了前面几种继承优点,几乎避免了上面继承方式的所有缺陷,是执行效率最高也是应用面最广的,就是实现的过程相对繁琐。
javascript中继承方式及优缺点(一)的更多相关文章
- javascript中继承方式及优缺点(三)
文以<JavaScript高级程序设计>上的内容为骨架,补充了ES6 Class的相关内容,从我认为更容易理解的角度将继承这件事叙述出来,希望大家能有所收获. 1. 继承分类 先来个整体印 ...
- javascript中继承方式及优缺点(二)
一.原型链继承 方式1: 原型链继承 (1)流程: 1.定义父类型构造函数. 2.给父类型的原型添加方法. 3.定义子类型的构造函数. 4.创建父类型的对象赋值给子类型的原型. 5 ...
- JavaScript各种继承方式和优缺点
好久没写博客啦,嘻嘻,这个月是2017年的最后一个月啦,大家应该都开始忙着写年终总结了吧,嘻嘻,小颖今天给大家分享下Javascript中的几种继承方式以及他们的优缺点. 1.借助构造函数实现继承 原 ...
- 谈谈JavaScript中继承方式
聊一聊js中的继承 一.简单继承---使用原型赋值的方式继承,将实例化的对象,赋值给子级的原型 父级构造函数 function Parent(param) { this.name = 'parent' ...
- js各种继承方式和优缺点的介绍
js各种继承方式和优缺点的介绍 作者: default 参考网址2 写在前面 本文讲解JavaScript各种继承方式和优缺点. 注意: 跟<JavaScript深入之创建对象>一样,更像 ...
- Javascript中继承
Javascript中继承 构造函数继承 原型继承 call和apply继承 组合继承
- javascript中各种继承方式的优缺点
javascript中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现.下面对各种实现方式进行分析,总结各自的优缺点. 一 原型继承 let Super = functioin(name = ...
- javascript 中继承实现方式归纳
转载自:http://sentsin.com/web/1109.html 不同于基于类的编程语言,如 C++ 和 Java,javascript 中的继承方式是基于原型的.同时由于 javascrip ...
- 实现JavaScript中继承的三种方式
在JavaScript中,继承可以通过三种手法实现原型链继承 使用apply.call方法 对象实例间的继承. 一.原型链继承 在原型链继承方面,JavaScript与java.c#等语言类似 ...
随机推荐
- PostgreSQL编码格式:客户端服务器、客户端、服务器端相关影响
关于字符编码这块,官网链接: https://www.postgresql.org/docs/current/charset.html 刚刚写了几百字的东西因为断网,导致全没有了,重头再写,我就只想记 ...
- Spring基于SchedulingConfigurer实现定时任务
Spring 基于 SchedulingConfigurer 实现定时任务,代码如下: import org.springframework.scheduling.annotation.Schedul ...
- java使用顺序数组实现二叉树
顺序数组实现二叉树 实现原理 对于下标为index的节点其满足 1.左孩子节点的下标为2index+1 2.右孩子节点的下标为2index+2 代码实现 package tree; public cl ...
- linux小白家教学<一>
<数据中心规划与实施> 教学大纲 编写人:Allen 一. 课程教学内容及目标: (一) 知识目标 1.掌握企业级LINUX部署以及相关配置: 2.掌握LINUX操作系统基本的创建.删除 ...
- 使用Python的文本挖掘的特征选择/提取
在文本挖掘与文本分类的有关问题中,文本最初始的数据是将文档表示成向量空间模型的一个矩阵,而这个矩阵所拥有的就是不同的词,常采用特征选择方法.原因是文本的特征一般都是单词(term),具有语义信息,使用 ...
- 小知识 Sql 格式化工具 AutoPostBack后的定位 Post和Get区别 防止被 Fream
T-Sql 格式化工具 http://jinzb.name/Common/SqlFormat.html AutoPostBack后的定位问题: 给Page 增加属性,MaintainScrollPos ...
- hadoop离线数据存储和挖掘架构
前序: 当你把你知道的东西,写下来,让人看明白是一种境界:当你能把自己写下来的东西给人讲明白,又是另一种境界.在这个过程中,我们都需要历练. 基于hadoop集群下海量离线数据存储和挖掘分析架构: 架 ...
- Jquery.serializeArray()可看表单提交内容
- 韦东山嵌入式Linux学习笔记04--点亮开发板的一个LED灯
搜索开发板原理图LED的走线 LED8是网线接口的指示灯. 在这里我们尝试用汇编代码控制D10, 也就是LED1,它连接到EINT4/GPF4,读取芯片手册 有原理图可知,如果需要 ...
- tornado实现高并发爬虫
from pyquery import PyQuery as pq from tornado import ioloop, gen, httpclient, queues from urllib.pa ...