JavaScript_几种继承方式(2017-07-04)
原型链继承
核心: 将父类的实例作为子类的原型
//父类
function SuperType() {
this.property = true;
} SuperType.prototype.getSuperValue = function () {
return this.property
}; //子类
function SubType() {
this.subproperty = false;
} //拿父类实例来充当子类原型对象
SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function () {
return this.subproperty
}; var instance = new SubType();
console.log(instance.getSuperValue()); //true
特点:
- 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
- 父类新增原型方法/原型属性,子类都能访问到
- 简单,易于实现
缺点:
- 要想为子类新增属性和方法,必须要在
new语句之后执行,不能放到构造器中 - 无法实现多继承
- 来自原型对象的引用属性是所有实例共享的
- 创建子类实例时,无法向父类构造函数传参
借用构造继承
核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
//父类
function SuperType() {
this.colors = ["red", "blue"]
}
//子类
function SubType() {
SuperType.call(this);//通过apply()和call()方法在新创建的对象上执行构造函数
} var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); //["red", "blue", "black"] var instance2 = new SubType();
console.log(instance2.colors); //["red", "blue"]
传递参数
//父类
function SuperType(name) {
this.name = name;
}
//子类
function SubType() {
SuperType.call(this, "mnixu");//通过apply()和call()方法在新创建的对象上执行构造函数
this.age = 20;
} var instance1 = new SubType();
console.log(instance1.name); //"mnixu"
console.log(instance1.age); //20
特点:
- 解决了原型链继承中,子类实例共享父类引用属性的问题
- 创建子类实例时,可以向父类传递参数
- 可以实现多继承(call多个父类对象)
缺点:
- 实例并不是父类的实例,只是子类的实例
- 只能继承父类的实例属性和方法,不能继承原型属性/方法
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
组合继承(最常用的继承模式)
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
//通过借用构造函数实现继承父类构造函数的属性(构造函数通常用this.属性,对实例对象来说私有)。
//使用原型链实现继承父类原型的属性和方法(原型的属性和方法,对实例对象来说共享)。
//父类
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue"];
} SuperType.prototype.sayName = function() {
console.log(this.name);
}
//子类
function SubType(name, age) {
SuperType.call(this, name);//通过apply()和call()方法在新创建的对象上执行构造函数
this.age = age;
} SubType.prototype = new SuperType();//拿父类实例来充当子类原型对象
SubType.prototype.constructor = SubType;//重新生成constructor属性指向子类,模型原型对象
SubType.prototype.sayAge = function() {
console.log(this.age);
}; var instance1 = new SubType("mnixu", 20);
instance1.colors.push("black");
console.log(instance1.colors); //["red", "blue", "black"]
instance1.sayAge(); //
instance1.sayName(); // "mnixu" var instance2 = new SubType("zwj", 28);
console.log(instance2.colors); //["red", "blue"]
instance2.sayAge(); //
instance2.sayName(); //"zwj"
特点:
- 弥补了借用构造函数继承方式的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
- 既是子类的实例,也是父类的实例
- 不存在引用属性共享问题
- 可传参
- 函数可复用
缺点:
- 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
4.原型式继承
借助原型并基于已有的对象创建新对象,同时还不用创建自定义类型
//生成对象的函数
function object(o) { //部分浏览器支持Object.create()方法
function F() {};
F.prototype = o;
return new F();
} //父类
var Person = {
name: "mnixu",
color: ["blue", "black"]
}
//子对象1
var anotherPerson = object(Person);
anotherPerson.name = "Greg";
anotherPerson.color.push("red")
//子对象2
var yetAnotherPerson = object(Person);
yetAnotherPerson.name = "zwj";
yetAnotherPerson.color.push("white") console.log(anotherPerson.color); //["blue", "black", "red", "white"]
console.log(yetAnotherPerson.color); //["blue", "black", "red", "white"]
原型式继承首先在obj()函数内部创建一个临时性的构造函数 ,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。
5.寄生式继承
这种继承方式是把原型式+工厂模式结合起来,目的是为了封装创建的过程。
//生成对象的函数
function object(o) { //部分浏览器支持Object.create()方法
function F() {};
F.prototype = o;
return new F();
} //生成并增强对象的函数
function createAnother(original){
var clone = object(original); //通过调用函数创建一个新对象
clone.sayHi = function(){ //增强这个对象
console.log("hi")
};
return clone; //返回这个对象
}
//父类
var Person = {
name: "mnixu",
color: ["blue", "black"]
}
//子对象
var anotherPerson = createAnother(Person);
anotherPerson.sayHi();
略
6.寄生组合式继承
核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
//生成对象的函数
function object(o) {//部分浏览器支持Object.create()方法
function F() {};
F.prototype = o;
return new F();
} //继承原型函数
function inheritPrototype(subType, superType) {
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
//父类
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue"];
} 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);
};
特点:
- 这个例子的高效率体现在只调用了一次SuperType构造函数,避免了在SubType.prototype上面创建不必要的属性,并且,原型链还能保持不变。堪称完美
缺点:
- 实现较为复杂
copy:
重新理解JS的6种继承方式js高级程序设计笔记 -- 理解继承
JavaScript_几种继承方式(2017-07-04)的更多相关文章
- js的三种继承方式及其优缺点
[转] 第一种,prototype的方式: //父类 function person(){ this.hair = 'black'; this.eye = 'black'; this.skin = ' ...
- 重新理解JS的6种继承方式
写在前面 一直不喜欢JS的OOP,在学习阶段好像也用不到,总觉得JS的OOP不伦不类的,可能是因为先接触了Java,所以对JS的OO部分有些抵触. 偏见归偏见,既然面试官问到了JS的OOP,那么说明这 ...
- C++的三种继承方式简述
C++对父类(也称基类)的继承有三种方式,分别为:public继承.protected继承.private继承.三种继承方式的不同在于继承之后子类的成员函数的"可继承性质". 在说 ...
- Javascript的四种继承方式
在Javascript中,所有开发者定义的类都可以作为基类,但出于安全性考虑,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击. 选定基类后,就可 ...
- JavaScript之四种继承方式讲解
在Javascript中,所有开发者定义的类都可以作为基类,但出于安全性考虑,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击. 选定基类后,就可 ...
- C++中的类继承(1) 三种继承方式
继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一.简单的说,继承是指一个对象直接使用另一对象的属性和方法.继承呈现了 面向对象程序设 计的层次结构, 体现了 由简单到复杂的认知过程. ...
- C++继承(一) 三种继承方式
继承定义 继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一. 继承就是不修改原有的类,直接利用原来的类的属性和方法并进行扩展.原来的类称为基类,继承的类称为派生类,他们的关系就像父子 ...
- c++三种继承方式public,protect,private
C++中的三种继承public,protected,private 三种访问权限 public:可以被任意实体访问 protected:只允许子类及本类的成员函数访问 private:只允许本类的成员 ...
- JavaScript的3种继承方式
JavaScript的继承方式有多种,这里列举3种,分别是原型继承.类继承以及混合继承. 1.原型继承 优点:既继承了父类的模板,又继承了父类的原型对象: 缺点:不是子类实例传参,而是需要通过父类实例 ...
随机推荐
- SSH原理与运用:远程登录
一.什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录. 如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会 ...
- windows Tomcat apr安装
背景 这都是当时不了解这个东西,又怕忘了记下来的,其实试验后.也就那么回事. 转载 Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO ...
- c++ 引用方式传递数组
值传递 (pass by value),指针传递(pass by pointer),当发生函数调用时,需要给形参分配存储单元.当传递是对象时,要调用拷贝构造函数.而且指针最后析构时,要处理内存释放问题 ...
- sqlyog通过跳板机ssh连接mysql数据库
方法一: 方法二: 在跳板机上启动sh脚本做ssh端口转发,客户端配置连接 10.0.0.1的8306端口即可 jdbc:mysql://10.0.0.1:8306/testdb?useUnicode ...
- 网站遭遇CC及DDOS攻击紧急处理方案
检测访问是否是CC攻击的命令: 80口为网站的访问端口,可以根据实际情况进行修改 # netstat -anlp|grep 80|grep tcp|awk '{print $5}'|awk -F: ' ...
- Linux常用命令3(压缩和解压缩总结)
tar命令 解包:tar zxvf FileName.tar 打包:tar czvf FileName.tar DirName gz命令 解压1:gunzip FileName.gz 解压2:gzip ...
- HTTP基础知识1
HTTP 简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准,它是基于TCP/IP ...
- LeetCode(56):合并区间
Medium! 题目描述: 给出一个区间的集合,请合并所有重叠的区间. 示例 1: 输入: [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18] ...
- Luogu P2426 【删数】
状态定义: 一眼区间$DP$,从左右两边删不好定义状态,不如定义$dp[i][j]$表示$[i,j]$未删的最大值,转移就很自然了 转移: 从左边删$dp[i][j]=max(dp[i][j],dp[ ...
- 使用siege执行压力测试
没有安装siege? 可参考我的另一篇博客 使用siege执行压力测试笔记 场景分析 使用siege对https://www.baidu.com/进行加压. 要求 模拟20个用户同时访问 一共跑3个循 ...