美文网首页
JS继承之extends

JS继承之extends

作者: 酷酷的凯先生 | 来源:发表于2020-08-15 09:39 被阅读0次

ES6中有关 class 的继承方式,引入了 extends 关键字。
但其本质仍然是 构造函数 + 原型链的 组合式继承。

class A {
   constructor(name, age) {
       this.name = name;
       this.age = age;
   }
   getName() {
       console.log( this.name );
   }
}

class B extends A {
   constructor(name, age) {
       super(name, age);
       this.job = "web";
   }
   getJob() {
       console.log( this.job );
   }
   getNameAndJob() {
       onsole.log( super.getName() + this.job );
   }
}

var b = new B("小黄", 20);
console.log(b.name); //小黄
console.log(b.age); //20
b.getName(); //小黄
b.getJob(); //web
b.getNameAndJob(); //小黄 web

# extends

上述 B 类(class)通过 extends 关键字,继承了 A 类 的所有属性和方法。A 类中的所有方法默认是添加到 B 的原型上,所以 extends 继承的实质仍然是原型链。

console.log("constructor" in b); //true
console.log("getName" in b); //true
console.log(b.hasOwnProperty("getName")); //false
console.log(b.hasOwnProperty("constructor")); //false

# super

super 这个关键字,既可以当作函数使用,也可以当作对象使用。当作函数使用时super 代表父类的构造函数,并在子类中执行 Parent.apply(this),从而将父类实例对象的属性和方法,添加到子类的 this上面。

特别注意

  1. 子类必须在 constructor 方法中调用 super 方法,如果子类没有定义 constructor 方法,constructor 方法以及其内部的 super 方法会被默认添加。
class A {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    getName() {
        console.log( this.name );
    }
}

class B extends A {}

var b = new B("小黄", 20);

console.log(b.name); //小黄
console.log(b.age); //20
b.getName(); //小黄
console.log(b.hasOwnProperty("name")); //true
  1. 在子类的 constructor 方法中,只有调用 super 之后,才可以使用 this 关键字,否则会报错。
class A {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}

class B extends A {
    constructor(name, age) {
        this.job = "web";
        super(name, age);
    }
}

var b = new B("小黄", 20); // 报错
  1. super() 只能用在子类的constructor方法之中,用在其他地方就会报错。
class A {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}

class B extends A {
    toStr(name, age) {
        super(name, age)
    }
}

var b = new B("Tom", 20); //报错

super 作为对象时,在子类中指向父类的原型对象。即 super = Parent.prototype

class A {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    getName() {
        console.log(this.name);
    }
}
A.prototype.n = 33;

class B extends A {
    constructor(name, age) {
        super(name, age);
    }
    toStr() {
        return super.n;
    }
    activeGetName() {
        super.getName();
    }
}

var b = new B("小黄", 20);
console.log(b.toStr());  //3
console.log(b.activeGetName()); //小黄

# 静态方法的继承

在一个方法前加上关键字 static,就表示该方法不会被实例继承,但是父类的静态方法,会被子类继承。

class A {
    static say() {
        console.log("hello");
    }
}

class B extends A {}

console.log(B.say()); //hello

也可以使用 super 在子类的静态方法中调用父类的静态方法。super 在静态方法中指向父类本身,而不是父类的原型对象。

class A {
    static say() {
        console.log("hello");
    }
}

class B extends A {
    static toStr() {
        super.say();
    }
}
var b = new B();
console.log(B.toStr()); //hello

# 继承表达式的类

类不但可以继承自其他类,也可以继承表达式。只要表达式可以被解析为一个函数并且通过 new 关键字可以创建新的实例对象即可。

  1. 继承传统形式的构造函数
let Obj = function(name) {
    this.name = name;
}
Obj.prototype.getName = function() {
    console.log(this.name);
}

class Person extends Obj {
    constructor(name, age) {
        super(name);
        this.age = age;
    }
}

const p = new Person("小黄", 29);

console.log(p.name); //小黄
console.log(p.age); //29
p.getName(); //小黄
  1. 继承函数返回结果
let fn = function() {
    return class Person {
        constructor(name) {
            return {
                name
            }
        }
    }
}

class SomeOne extends fn() {
    constructor(name) {
        super(name);
    }
}

let p = new SomeOne("小黄");
console.log(p.name); //小黄

# New.target

我们知道,函数内部有一个 new.target 对象用于判断函数是否通过new关键字调用。类构造函数也可以通过 new.target 来确定类的调用形式。

class Obj {
    //new Obj()时,new.target 的值为 Obj
    constructor() {
        if (new.target === Obj) {
            console.log("不可以直接调用基类!");
        }
    }
    fn() {
        console.log(this.name);
    }
}

class Person extends Obj {
    //new Person("小黄")时,new.target的值为 Person
    constructor(name) {
        super();
        this.name = name;
    }
}

let p1 = new Person("小黄");
p1.fn(); //小黄
let p2 = new Obj(); // 不可以直接调用基类!

因为类必须通过 new 关键字调用,所以在类的构造函数中 new.target 的值永远不会是undefined

相关文章

  • JS继承之extends

    ES6中有关 class 的继承方式,引入了 extends 关键字。但其本质仍然是 构造函数 + 原型链的 组合...

  • Js 类继承 extends

    html 及 js 代码

  • Dart 中的 extends / with / impleme

    extends extends 表示继承。Dart 中的继承和 Java 一样。 使用关键字 extends 继承...

  • TypeScript - 04 类

    类 上面等同于原生js 继承 class A extends B,A类继承B类所有的属性和方法 子类通过 supe...

  • 继承extends

    继承的好处: 1. 提高了代码的复用性; 2. 让类与类之间产生了关系,给第三种特征多态提供了前提。 单继承VS多...

  • 继承 extends

    继承中成员变量的访问特点 1、父子类继承关系中,成员变量重名时,子类对象访问重名变量的2种方式 子类对象直接访问成...

  • java中的继承

    继承的关键之是extends子类 extends 父类 继承的初始化顺序 初始化父类再初始化子类 先执行初始化对象...

  • 继承

    1.继承的实现-------extends class dog extends animal 2.子类可以继承父...

  • Java基础——继承(Extends)

    一、extends(继承)使用继承可以实现代码的重用,在java语言中,通过extends关键字实现类的继承。继承...

  • kotlin之open class继承

    7 kotlin之class继承open open表示可继承,extends也被改为: 喜欢可以加Q群号:8748...

网友评论

      本文标题:JS继承之extends

      本文链接:https://www.haomeiwen.com/subject/asfndktx.html