Javascirpt 面向对象总结-继承
JS继承的实现方式
既然要实现继承,那么首先我们得有一个父类,代码如下:
// 定义一个动物类
function Animal (name) {
// 公有属性
this.name = name || 'Animal';
// 实例方法
this.sleep = function(){
console.log(this.name + '正在睡觉!');
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + '正在吃:' + food);
};
1、原型链继承
核心: 将父类的实例作为子类的原型
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat'; // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
特点:
- 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
- 父类新增原型方法/原型属性,子类都能访问到
- 简单,易于实现
缺点:
- 无法实现多继承
- 来自原型对象的引用属性是所有实例共享的(详细请看附录代码: 示例1)
- 创建子类实例时,无法向父类构造函数传参
2、构造继承
核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
} // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特点:
- 解决了1中,子类实例共享父类引用属性的问题
- 创建子类实例时,可以向父类传递参数
- 可以实现多继承(call多个父类对象)
缺点:
- 实例并不是父类的实例,只是子类的实例
- 只能继承父类的实例属性和方法,不能继承原型属性/方法
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
3、实例继承
核心:为父类实例添加新特性,作为子类实例返回
function Cat(name){
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
} // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
特点:
- 不限制调用方式,不管是
new 子类()
还是子类()
,返回的对象具有相同的效果
缺点:
- 实例是父类的实例,不是子类的实例
- 不支持多继承
4、拷贝继承
function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || 'Tom';
} // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特点:
- 支持多继承
缺点:
- 效率较低,内存占用高(因为要拷贝父类的属性)
- 无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
5、组合继承
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat.prototype = new Animal(); // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
特点:
- 弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
- 既是子类的实例,也是父类的实例
- 不存在引用属性共享问题
- 可传参
- 函数可复用
缺点:
- 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
6、寄生组合继承
核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
(function(){
// 创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
Cat.prototype.constructor = Cat;
})(); // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
//将该继承行为封装为函数
function inherits(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
特点:
- 堪称完美
缺点:
- 实现较为复杂
附录代码:
function Animal (name) {
// 公有属性
this.name = name || 'Animal';
// 实例方法
this.sleep = function(){
console.log(this.name + '正在睡觉!');
}
//实例引用属性
this.features = [];
}
function Cat(name){
}
Cat.prototype = new Animal(); var tom = new Cat('Tom');
var kissy = new Cat('Kissy'); console.log(tom.name); // "Animal"
console.log(kissy.name); // "Animal"
console.log(tom.features); // []
console.log(kissy.features); // [] tom.name = 'Tom-New Name';
tom.features.push('eat'); //针对父类实例值类型成员的更改,不影响
console.log(tom.name); // "Tom-New Name"
console.log(kissy.name); // "Animal"
//针对父类实例引用类型成员的更改,会通过影响其他子类实例
console.log(tom.features); // ['eat']
console.log(kissy.features); // ['eat'] 原因分析: 关键点:属性查找过程 执行tom.features.push,首先找tom对象的实例属性(找不到),
那么去原型对象中找,也就是Animal的实例。发现有,那么就直接在这个对象的
features属性中插入值。
在console.log(kissy.features); 的时候。同上,kissy实例上没有,那么去原型上找。
刚好原型上有,就直接返回,但是注意,这个原型对象中features属性值已经变化了。
Javascirpt 面向对象总结-继承的更多相关文章
- 黑马程序员_Java面向对象2_继承
4.面向对象_继承 4.1继承的概述 提高了代码的复用性. 让类与类之间产生了关系,有了这个关系,才有多态的特性. 注意:千万不要为了获取其他类的功能而去继承,简化代码而继承.必须是类与类之间有所属关 ...
- C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域
面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:假设不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这样的类作用域的层次嵌套使 ...
- 【Java基础】【08面向对象_继承&方法&final】
08.01_面向对象(代码块的概述和分类)(了解)(面试的时候会问,开发不用或者很少用) A:代码块概述 在Java中,使用{}括起来的代码被称为代码块. B:代码块分类 根据其位置和声明的不同,可以 ...
- php面向对象 封装继承多态 接口、重载、抽象类、最终类总结
1.面向对象 封装继承多态 接口.重载.抽象类.最终类 面向对象 封装继承多态 首先,在解释面向对象之前先解释下什么是面向对象? [面向对象]1.什么是类? 具有相同属性(特征)和方法(行为)的一 ...
- 面向对象多继承(c3算法)、网络基础和编写网络相关的程序
一.面向对象多继承(c3算法) a.有多个父类先找左,再找右,如下示例: class A(object): pass class B(object): def f1(self): print('B') ...
- Python 面向对象编程 继承 和多态
Python 面向对象编程 继承 和多态 一:多继承性 对于java我们熟悉的是一个类只能继承一个父类:但是对于C++ 一个子类可以有多个父亲,同样对于 Python一个类也可以有多个父亲 格式: c ...
- python之面向对象(继承)
类的继承 python之面向对象(继承) 面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制.继承完全可以理解成类之间的类型和子类型关系. 需要注意的地方:继承语法 c ...
- python面向对象编程 继承 组合 接口和抽象类
1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均用点来访问自己的 ...
- Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类
一.前提回忆: 1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均 ...
随机推荐
- TCP通信简单梳理
一.什么是TCP协议 TCP协议是一种面向连接的可靠的通信协议,最重要的两个特点:连接.可靠. 二.TCP是如何进行通信的 TCP通过三次握手建立连接后客户端服务端的内核都分别开辟资源,这时候开始进行 ...
- jvm源码解读--18 Java的start()方法解读 以及 wait 和notify流程图
drawwed by 张艳涛 and get info from openjdk8 还有一个图
- C#曲线分析平台的制作(二,echarts前后台数据显示)
在上一篇博客中,学习了使用javascript和jquery两种方法来进行前后台交互.本篇博客着重利用jquery+echarts来实现从后台取数,从前端echarts中展示. 1.html页面编写: ...
- 电脑软件安装过程文档.BA
MD 01-打印并阅读-电脑软件安装过程文档.BAT-即此批处理脚本文档MD 02-阅读-电脑软件安装经验教训文档.DOCX-MD 03-制作-杏雨梨云USB维护系统2019中秋版之国庆更新-可启动U ...
- centos7 安装mariadb、"systemctl status mariadb.service" and "journalctl -xe" for details
centos7 mariadb 安装 也可解决此错误:ob for mariadb.service failed because the control process exited with err ...
- etcd raft 处理流程图系列2-wal的读写
本文仅介绍wal的基本处理,如create.open.close.read等操作.鉴于篇幅原因,下面介绍replayWAL(启动raft节点时执行)函数涉及的读文件操作:从wal目录中加载snapsh ...
- C++ //多态案例三 ---电脑组装
1 //多态案例三 ---电脑组装 2 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 ...
- 方法对了,你做1年Android开发能顶别人做10年
前几天后台有读者问我这样的问题.他在一家互联网公司工作3年了,每天都很忙,事情又多又杂. 本想着学习多一些东西也不是坏事,可到头来一无所获,什么都没学会,满腔的热情也被消磨得差不多. 三天两头动辞职的 ...
- C++STL——vector类
vector容器 1.1 vector容器的基本概念 Array 是静态空间,一旦配置了就不能改变,要换大一点或者小一 点的空间,可以,一切琐碎得由自己来,首先配置一块新的空间,然后将旧空间的 数据搬 ...
- 用华为云cli,管理华为云服务器的,安全组端口
---[前言]--- 关键字 hcloud 华为 命令行 linux windows powershell 前些天,大家因为华为云,是否应该默认开启端口,大家吵起来了,所以我抽空写了此文.解决问题,缓 ...