子类 extends 父类
class Point {
}
class ColorPoint extends Point {
}
class ColorPoint extends Point {
}
// 等同于
class ColorPoint extends Point {
constructor(...args) {
super(...args);
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
// this.color = color; 这里会报错
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}
class A {
a() {
}
static aa(){
console.log('aa')
}
}
class B extends A {
b() {
}
}
var b = new B()
// 父类的静态方法,被子类继承。
B.aa() // aa
b.aa() // Uncaught TypeError: b.aa is not a function
// 说明 B.__proto__ === A
// 当构造函数通过new来生成实例时,构造函数的prototype属性将被自动转为__proto__作为实例的原型链(只有对象在执行方法时,会顺着__proto__去找对象本身没有的方法)
// 类的方法位于类的prototype属性上
// 所以 B.prototype === A.prototype; // false
// 为什么是false? 因为这是es5的实现方法,父类先直接覆盖子类的prototype,后写入子类方法(如果后覆盖会把先写入的子类方法覆盖掉)
// 那怎么办 我们打印 B.prototype 属性,发现里面有一个__proto__属性,原来es6是把父类prototype属性挂在子类的prototype.__proto__上面了,对象在调用方法时,如果找不到对应的方法,那么会沿着__proto__属性一直往上找。
// 所以有 B.prototype.__proto__ === A.prototype; // true
es6 的两个满足条件就是 :
B.proto === A // true 静态方法继承
B.prototype.proto === A.prototype; // true 属性方法继承
Object.getPrototypeOf(B) === A // true
function A(){
...
}
A.staticA = function(){}
A.prototype.A = function(){}
class B {
constructor() {
A.prototype.constructor.call(this) // 关键
}
b() {
console.log('bar')
}
}
// 核心:两条原型链
B.__proto__ = A
B.prototype.__proto__ = A.prototype
// 然后就完成了
super 这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
class A {}
class B extends A {
constructor() {
super(); // super()在这里相当于A.prototype.constructor.call(this)。
}
}
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
class Parent {
static myMethod(msg) {
console.log('static', msg);
}
myMethod(msg) {
console.log('instance', msg);
}
}
class Child extends Parent {
static myMethod(msg) {
super.myMethod(msg);
}
myMethod(msg) {
super.myMethod(msg);
}
}
Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2
class A {
constructor() {
this.p = 2;
}
}
class B extends A {
get m() {
return super.p;
}
}
let b = new B();
b.m // undefined
class A {}
A.prototype.x = 2;
class B extends A {
constructor() {
super();
console.log(super.x) // 2
}
}
let b = new B();
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
class A {
constructor() {
this.x = 1;
}
static print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
static m() {
super.print();
}
}
B.x = 3;
B.m() // 3
class A {
}
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
class MyArray extends Array {
constructor(...args) {
super(...args);
}
}
var arr = new MyArray();
arr[0] = 12;
arr.length // 1
arr.length = 0;
arr[0] // undefined
class NewObj extends Object{
constructor(){
super(...arguments);
}
}
var o = new NewObj({attr: true});
o.attr === true // false
等等… 更多继承参考阮一峰 es6
function mix(...mixins) {
class Mix {
constructor() {
for (let mixin of mixins) {
copyProperties(this, new mixin()); // 拷贝实例属性
}
}
}
for (let mixin of mixins) {
copyProperties(Mix, mixin); // 拷贝静态属性
copyProperties(Mix.prototype, mixin.prototype); // 拷贝原型属性
}
return Mix;
}
function copyProperties(target, source) {
for (let key of Reflect.ownKeys(source)) {
if ( key !== 'constructor'
&& key !== 'prototype'
&& key !== 'name'
) {
let desc = Object.getOwnPropertyDescriptor(source, key);
Object.defineProperty(target, key, desc);
}
}
}
参考博文 阮一峰 es6