class(二)--派生类的继承
前言
从我之前的一篇笔记对象的继承中, 我们可以知道JS的继承方式依赖原型链,而比较好的继承方式是寄生组合式继承
先来温习下什么是寄生组合式继承
function Rectangle(length, width) {
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function() {
return this.length * this.width;
};
function Square(length) {
Rectangle.call(this, length, length);
// 1 调用父类构造函数
}
Square.prototype = Object.create(Rectangle.prototype, {
constructor: {
value:Square,
enumerable: true,
writable: true,
configurable: true
}
});
// 2 Object.create会在内部创建一个空对象来连接两个原型对象, 再手动将constructor指向自身
var square = new Square(3);
console.log(square.getArea()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true
- 在子构造函数中调用父级构造函数,来将属性定义在自己身上
- 原型继承主要是为了继承原型对象上的方法
这就是在ES6
之前的继承方式,对原型链理解不够深透的话很容易混乱
但在ES6
推出class
这个类之后,一切都变得简单(再次提醒:class
只是语法糖,实质就是对寄生组合式继承
的封装
派生类进行继承
首先我们将继承其他类的的类称为派生类(derived classes)
, 再来看看上面的例子, 利用class
如何轻松实现
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
return this.length * this.width;
}
}
class Square extends Rectangle {
constructor(length) {
// 与 Rectangle.call(this, length, length) 相同
super(length, length);
}
}
var square = new Square(3);
console.log(square.getArea()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true
console.log(Square.prototype.constructor === Square) // true
实现继承只需要两步
class
上extends
继承父类- 在构造函数中调用
super()
super
也是ES6
中的内容,它是指向当前对象的原型
的一个指针,实际上就是Object.getPrototypeOf(this)
的值。
根据上面的例子我们来看下
Object.getPrototypeOf(Square) === Rectangle // true
那super(length, lenght)
应该是Rectangle(lenght, length)
才对啊,其实在ES6
中真正出现了方法
的概念,从前只能说是一个函数属性, 在方法中会有一个内部属性[[HomeObject]]
任何对super
的引用都会使用[[HomeObject]]
属性来判断要做什么。第一步是在[[HomeObject]]
上调用Object.getPrototypeOf()
来获取对原型的引用;最后,创建this绑定并调用该方法的对象
。因此是Rectangle.call(this, length, length)
注意点:
- 使用了
extends
就必须在构造器中调用super()
super
必须要在this
前面- 要想不用
super()
:
- 不用构造器, 它会默认创建,并按照顺序传入所有参数
return
返回一个对象,不能是number
等基本数据类型,否则return
的是this
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
return this.length * this.width;
}
}
// 不传super()
class Square extends Rectangle {
constructor(length) {
}
}
let s1 = new Square(3) //Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructorat new Square
// 报错 必须在访问this前面调用super构造器或者在返回一个新的Square实例对象必须调用super构造器
// 直接不传入构造器
class Square extends Rectangle {}
let s2 = new Square(3, 4)
console.log(s2.getArea()) //12
console.log(s2.width) // 4
console.log(s2.length) // 3
// 其实默认调用了构造器
//class Square extends Rectangle {
// constructor(...args) {
// super(...args)
// }
//}
// 返回一个对象
class Square extends Rectangle {
constructor(length) {
return {}
}
}
let s2 = new Square()
console.log(s2 instanceof Square) // false
继承静态成员
其实从之前的super
就能看出个大概了
Object.getPrototypeOf(Square) === Rectangle // true
因此Rectangle
的静态成员自然可以被Square
访问到
Rectangle.create = function(l, w) {
return new Rectangle(l, w)
}
console.log('create' in Square) // true
console.log(Square.hasOwnProperty('create')) // false
继承非类
其实只要一个表达式能够返回一个具有[[Construct]]
属性的以及原型
的函数,就可以对其实使用extends
一般来说,对象的原型
会在通过构造器
或Object.create()
方法创建该对象时被指定。而[[Construct]]
只有箭头函数没有
因此一下几种情况都是可以的
function Parent() {}
class Child extends Parent {
}
console.log(Child.prototype.__proto__ === Parent.prototype) // true
console.log(Child.__proto__ === Parent) // true
let SerializableMixin = {
serialize() {
return JSON.stringify(this);
}
};
let AreaMixin = {
getArea() {
return this.length * this.width;
}
};
function mixin(...mixins) {
var base = function() {};
Object.assign(base.prototype, ...mixins);
return base;
}
class Square extends mixin(AreaMixin, SerializableMixin) {
constructor(length) {
super();
this.length = length;
this.width = length;
}
}
var x = new Square(3);
console.log(x.getArea()); // 9
console.log(x.serialize()); // "{"length":3,"width":3}"
class(二)--派生类的继承的更多相关文章
- C++继承具体解释之二——派生类成员函数具体解释(函数隐藏、构造函数与兼容覆盖规则)
在这一篇文章開始之前.我先解决一个问题. 在上一篇C++继承详解之中的一个--初探继承中,我提到了在派生类中能够定义一个与基类成员函数同名的函数,这样派生类中的函数就会覆盖掉基类的成员函数. 在谭浩强 ...
- Python 派生类子类继承类
1.创建list类的子类Namedlist,初始化新类,创建新对象实例johnny,检查对象类型,并使用list的一些功能来存储数据 >>> class Namedlist(list ...
- java基础二、类与继承
员工类 Employee, 经理类:Manager public class Employee { private String name; private double salary; privat ...
- C++中类的继承与Java中的不同,C++的派生类不能继承父类的构造函数和析构函数(不一定正确)
http://blog.csdn.net/guodongxiaren/article/details/24885023
- c++ 的类 和 类继承, 什么是c++中的基类和派生类?
闲云潭影日悠悠,物换星移几度秋 你既然已经做出了选择, 又何必去问为什么选择.鬼谷绝学的要义, 从来都不是回答, 而是抉与择 普通类 #ifndef TABTENN0_H_ #define TABTE ...
- java类的继承(基础)
---恢复内容开始--- 这篇随笔和大家讲讲java中类的继承是什么?希望对你们有所帮助. 目录 一.java继承是什么? 二.为什么使用java继承 三.java继承的实现 1.1 java继承的 ...
- 面向对象【day07】:类的继承(七)
本节内容 1.概述 2.类的继承 3.总结 4.练习 一.概述 之前我们说到了类的公有属性和类的私有属性,其实就是类的封装,下面我们来讲讲继承,是面向对象的第二大特性. 面向对象编程 (OOP) 语言 ...
- C++基础知识-派生类、调用顺序、访问等级、函数遮蔽
一.派生类的概念 类之间有一种层次关系,有父亲类,有孩子类. 车这个类,当成父类(也叫基类.超类),派生出卡车.轿车,他们属于孩子类(子类.派生类) 继承:有父亲类,有孩子类,构成了层次关系.继承这种 ...
- OOP1(定义基类和派生类)
面向对象程序设计基于三个基本概念:数据抽象,继承和动态绑定 数据抽象是一种依赖于接口和实现分离的编程技术.继承和动态绑定对程序的编号有两方面的影响:一是我们可以更容易地定义与其它类相似但不完全相同的类 ...
随机推荐
- 吴裕雄--天生自然PYTHON爬虫:爬取某一大型电商网站的商品数据(效率优化以及代码容错处理)
这篇博文主要是对我的这篇https://www.cnblogs.com/tszr/p/12198054.html爬虫效率的优化,目的是为了提高爬虫效率. 可以根据出发地同时调用多个CPU,每个CPU运 ...
- 方法重载(Overload)
方法重载(Overload):多个方法名称一样,但参数列表不一样. (一个方法名称,实现类似的多个功能) 方法重载与下列因素有关: 1. 参数个数不同 public static int sum(in ...
- Linux三剑客之awk精讲(基础与进阶)
第1章 awk基础入门 要弄懂awk程序,必须熟悉了解这个工具的规则.本实战笔记的目的是通过实际案例或面试题带同学们熟练掌握awk在企业中的用法,而不是awk程序的帮助手册. 1.1 awk简介 一种 ...
- HackerOne去年发放超过8200万美元的赏金,联邦政府参与度大幅上涨
2019年,由黑客驱动的漏洞赏金平台HackerOne支付的漏洞奖金几乎是前几年总和的两倍,达到8200万美元. HackerOne平台在2019年也将注册黑客数量翻了一番,超过了60万,同时全年收到 ...
- 「HNOI2004」宠物收养场
「HNOI2004」宠物收养场 传送门 对宠物和人各维护一棵平衡树,每次 \(\text{split}\) 的时候记得判一下子树是否为空,然后模拟就好了. 参考代码: #include <alg ...
- A Simple Problem with Integers-POJ3468 区间修改+区间查询
题意: 给你n个数和2个操作,C操作是将一个区间内的每个数都加上k,Q操作是询问一个区间的和 链接:http://poj.org/problem?id=3468 思路: 线段树区间修改+区间查询 代码 ...
- HTML相关知识点(2)
CSS: 字体: 网页默认字体16px; 网站通用字体大小14px 最小是12px,最大无限大 单位换算:1em=16px 选择器:标签选择器:选择页面中所有指定标签,权重为1 通配符选择器:选择所 ...
- windowsService 程序
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- HDFS 命令行基本操作
1.hdfs命令行 (1)查看帮助 hdfs dfs -help (2)查看当前目录信息 hdfs dfs -ls / (3)上传文件 hdfs dfs -put /本地路径 /hdfs路径 (4)剪 ...
- 今日份学习:初步的springboot
今日记录 今日份BUG清单 flyway的sql文件有两个下划线 __ , _ 是不可以的. 高版本的freemarker默认的扩展名变成了flth,而不是ftl 今日份用到的网址 1. freema ...