网站地图    收藏   

主页 > 前端 > javascript >

JavaScript继承之ES6的extends

来源:未知    时间:2020-02-01 20:14 作者:小飞侠 阅读:

[导读] JavaScript继承之ES6的extends 例子: classA{constructor(name,age){this.name=name;this.age=age;}getName(){returnthis.name;}}classBextendsA{constructor(name,age){super(name,age);this.job=IT;}getJob(){returnthis.job;}getNameAndJob(){retu...

JavaScript继承之ES6的extends

例子:

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

class B extends A {
    constructor(name, age) {
        super(name, age);
        this.job = "IT";
    }
    getJob() {
        return this.job;
    }
    getNameAndJob() {
        return super.getName() + this.job;
    }
}

var b = new B("Tom", 20);
console.log(b.name);
console.log(b.age);
console.log(b.getName());
console.log(b.getJob());
console.log(b.getNameAndJob());
//输出:Tom,20,Tom,IT,TomIT

重点解析之extends关键字

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

测试代码:

console.log("constructor" in b);
console.log("getName" in b); 
console.log(b.hasOwnProperty("getName"));
console.log(b.hasOwnProperty("constructor"));
//输出:true,true,false,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() {
        return this.name;
    }
}

class B extends A {}

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

console.log(b.name);
console.log(b.age);
console.log(b.getName());
console.log(b.hasOwnProperty("name"));
//输出:Tom,20,Tom,true

2、在子类的constructor方法中,只有调用super之后,才可以使用this关键字,否则会报错。

测试代码:

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

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

var b = new B("Tom", 20)
//输出:报错

3、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 = 2;

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

var b = new B("Tom", 20);
console.log(b.toStr());
console.log(b.activeGetName());
//输出:2,Tom

重点解析之静态方法的继承

在一个方法前加上关键字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("Tom", 19);

console.log(p.name); //输出:Tom
console.log(p.age); //输出:19
p.getName(); //输出:Tom

例子2:
继承函数返回结果

let fn = function() {
    return class Person {
        constructor(name) {
            return {
                name
            }
        }
    }
}

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

let p = new SomeOne("Tom");
console.log(p.name); //输出:Tom

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("Tom")时,new.target的值为 Person
    constructor(name) {
        super();
        this.name = name;
    }
}

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

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




自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论