JavaScript高级学习:ES6新特性10——继承的学习01

提示:
本文为JavaScript栏目:JavaScript高级系列——ES6新特性章节 第十章


前言

本文粗浅学习继承。


提示:以下是本篇文章正文内容,下面案例可供参考

继承

ES5与ES6中继承用法的对比

ES5中继承的用法

ES5中的继承实际上是通过代码的灵活运用,让s去自动同步了F的代码,写法是多种不固定的。

function F() {
    this.color="red";
    this.name="dog";
}
F.prototype.age=10;

function S() {
    /*构造函数的继承*/
    this.name=20;  //语句1
    F.call(this);
    this.x=10;
}
/*原型继承*/
for(let k in F.prototype){
    S.prototype[k]=F.prototype[k];
}

ES5中同名属性在父类构造调用前先赋值,会被F.call给覆盖,造成赋值无效 ,如语句1

ES5中的继承只能继承自定义的构造函数,内置的构造函数是无法继承。比如(Math,Date);

ES6中继承的用法

class A{
    constructor(sex) {
        this.name="张三";
        this.sex=sex;
        console.log(this);  //A还是B
    }
    age=22;
}
class B extends A{
    constructor(){
        super("boy");
        
        this.x=10;
    }
    show(){
    }
}
let b=new B();
console.log(b.name);    //张三
console.log(b.age);     //22
console.log(b.sex);     //boy
console.log(b.x);       //10

解析:

父类A:

class A{
    constructor(sex) {
        this.name="张三";
        this.sex=sex;
        console.log(this);  //A还是B
    }
    age=22;
}

/*在ES6中class可以通过extents关键字来实现类的继承
* class B extends A 表示A为父类,B为子类
* 这个时候子类(B类)可以使用A类中所有的非私有属性和方法*/
class B extends A{
    /*子类中可以不写构造函数,代码在运行时会自动加上构造函数和super(),如果自己写了构造函数,就一定要记得调用super()*/
    constructor(){
        // this.x=5;
        /*父级构造函数需要传参,子类调用父类构造函数时,可以传参,也可以不传参,这一点和java是不一样的,我们推荐传参使用*/
        super("boy");    //调用父级的构造函数,子类中必读调用父类构造函数!!!!
        /*this关键字必须在super之后使用*/
        this.x=10;
    }
    show(){
        /*super()表示的是父类构造函数的调用,只能写在子类的构造函数中。*/
        /*普通方法不能使用super()函数,但是可以使用super关键字表示super对象*/
        // super();
    }
}

// let a=new A();
let b=new B();
console.log(b.name);    //张三
console.log(b.age);     //22
console.log(b.sex);     //boy
console.log(b.x);       //10
class A{
    constructor(sex) {
        this.name="张三";
        this.sex=sex;
        console.log(this);  //A还是B
    }
    age=22;
}

/*在ES6中class可以通过extents关键字来实现类的继承
* class B extends A 表示A为父类,B为子类
* 这个时候子类(B类)可以使用A类中所有的非私有属性和方法*/
class B extends A{
    /*子类中可以不写构造函数,代码在运行时会自动加上构造函数和super(),如果自己写了构造函数,就一定要记得调用super()*/
    constructor(){
        // this.x=5;
        /*父级构造函数需要传参,子类调用父类构造函数时,可以传参,也可以不传参,这一点和java是不一样的,我们推荐传参使用*/
        super("boy");    //调用父级的构造函数,子类中必读调用父类构造函数!!!!
        /*this关键字必须在super之后使用*/
        this.x=10;
    }
    show(){
        /*super()表示的是父类构造函数的调用,只能写在子类的构造函数中。*/
        /*普通方法不能使用super()函数,但是可以使用super关键字表示super对象*/
        // super();
    }
}

// let a=new A();
let b=new B();
console.log(b.name);    //张三
console.log(b.age);     //22
console.log(b.sex);     //boy
console.log(b.x);       //10
class A{
    constructor(sex) {
        this.name="张三";
        this.sex=sex;
        console.log(this);  //A还是B
    }
    age=22;
}

/*在ES6中class可以通过extents关键字来实现类的继承
* class B extends A 表示A为父类,B为子类
* 这个时候子类(B类)可以使用A类中所有的非私有属性和方法*/
class B extends A{
    /*子类中可以不写构造函数,代码在运行时会自动加上构造函数和super(),如果自己写了构造函数,就一定要记得调用super()*/
    constructor(){
        // this.x=5;
        /*父级构造函数需要传参,子类调用父类构造函数时,可以传参,也可以不传参,这一点和java是不一样的,我们推荐传参使用*/
        super("boy");    //调用父级的构造函数,子类中必读调用父类构造函数!!!!
        /*this关键字必须在super之后使用*/
        this.x=10;
    }
    show(){
        /*super()表示的是父类构造函数的调用,只能写在子类的构造函数中。*/
        /*普通方法不能使用super()函数,但是可以使用super关键字表示super对象*/
        // super();
    }
}

// let a=new A();
let b=new B();
console.log(b.name);    //张三
console.log(b.age);     //22
console.log(b.sex);     //boy
console.log(b.x);       //10
class A{
    constructor(sex) {
        this.name="张三";
        this.sex=sex;
        console.log(this);  //A还是B
    }
    age=22;
}

/*在ES6中class可以通过extents关键字来实现类的继承
* class B extends A 表示A为父类,B为子类
* 这个时候子类(B类)可以使用A类中所有的非私有属性和方法*/
class B extends A{
    /*子类中可以不写构造函数,代码在运行时会自动加上构造函数和super(),如果自己写了构造函数,就一定要记得调用super()*/
    constructor(){
        // this.x=5;
        /*父级构造函数需要传参,子类调用父类构造函数时,可以传参,也可以不传参,这一点和java是不一样的,我们推荐传参使用*/
        super("boy");    //调用父级的构造函数,子类中必读调用父类构造函数!!!!
        /*this关键字必须在super之后使用*/
        this.x=10;
    }
    show(){
        /*super()表示的是父类构造函数的调用,只能写在子类的构造函数中。*/
        /*普通方法不能使用super()函数,但是可以使用super关键字表示super对象*/
        // super();
    }
}

// let a=new A();
let b=new B();
console.log(b.name);    //张三
console.log(b.age);     //22
console.log(b.sex);     //boy
console.log(b.x);       //10
class A{
    constructor(sex) {
        this.name="张三";
        this.sex=sex;
        console.log(this);  //A还是B
    }
    age=22;
}

/*在ES6中class可以通过extents关键字来实现类的继承
* class B extends A 表示A为父类,B为子类
* 这个时候子类(B类)可以使用A类中所有的非私有属性和方法*/
class B extends A{
    /*子类中可以不写构造函数,代码在运行时会自动加上构造函数和super(),如果自己写了构造函数,就一定要记得调用super()*/
    constructor(){
        // this.x=5;
        /*父级构造函数需要传参,子类调用父类构造函数时,可以传参,也可以不传参,这一点和java是不一样的,我们推荐传参使用*/
        super("boy");    //调用父级的构造函数,子类中必读调用父类构造函数!!!!
        /*this关键字必须在super之后使用*/
        this.x=10;
    }
    show(){
        /*super()表示的是父类构造函数的调用,只能写在子类的构造函数中。*/
        /*普通方法不能使用super()函数,但是可以使用super关键字表示super对象*/
        // super();
    }
}

// let a=new A();
let b=new B();
console.log(b.name);    //张三
console.log(b.age);     //22
console.log(b.sex);     //boy
console.log(b.x);       //10

父类

class A{
    constructor(sex) {
        this.name="张三";
        this.sex=sex;
        console.log(this);  //A还是B的问题
        //let a=new A();	输出为A	{age: 22, name: "张三", sex: undefined}
        //let b=new B();	输出为B	{age: 22, name: "张三", sex: "boy"}
        
    }
    age=22;
}

在ES6中class可以通过extents关键字来实现类的继承

class B extends A 表示A为父类,B为子类。这个时候子类(B类)可以使用A类中所有的非私有属性和方法

class B extends A{
    constructor(){
        super("boy");//语句2
        this.x=10;	//语句3
    }
    show(){
    }
}
let b=new B();

子类中可以不写构造函数,代码在运行时会自动加上构造函数和super(),如果自己写了构造函数,就一定要记得调用super(),比如语句2。

父级构造函数需要传参,子类调用父类构造函数时,可以传参,也可以不传参,这一点和java是不一样的,我们推荐传参使用。但是调用父级的构造函数,子类中必读调用父类构造函数!!!!如语句2

this关键字必须在super之后使用,比如语句3

super()表示的是父类构造函数的调用,只能写在子类的构造函数中。普通方法不能使用super()函数,但是可以使用super关键字表示super对象,如:

class B extends A{
    constructor(){
        super("boy"); 
        this.x=10;
    }
    show(){
        super();
    }
}
let b=new B();
console.log(b.name);    //张三
console.log(b.age);     //22
console.log(b.sex);     //boy
console.log(b.x);       //10

super关键字的使用

super关键字作为对象使用

class A{
    constructor() {
        this.name="张三";
        this.show=function () {
            console.log("A的构造函数中的方法");
        }
    }
    age=18; 
    play() {
        console.log(this);
        console.log(this.abc);  
        console.log("A的构造函数中的原型方法");
    }
}
A.prototype.sex="男";

let a =new A();
console.log(a.play());

class B extends A{
    constructor() {
        super();
        this.abc="abc";
        super.def="def";
        console.log(super.def); 
        console.log(super.name);
        console.log(super.age);
        console.log(super.sex);
        super.play();
    }
}

let b=new B();
console.log(b);
let aa=new A();
console.log(aa);

解析

父类A

class A{
    constructor() {
        this.name="张三";
        this.show=function () {
            console.log("A的构造函数中的方法");
        }
    }
    age=18; //不使用constructor函数直接写的属性也属于实例属性,但是要求必须在类的最顶层
    play() {
        console.log(this);
        console.log("A的构造函数中的原型方法");
    }
}
A.prototype.sex="男";

let a =new A();
console.log(a.play());
/*
A
A的构造函数中的原型方法
*/

子类B

子类中的super和父类中的this是等价的,如语句4

class A{
    
    play() {
        console.log(this);
        console.log(this.abc);  //子类中有abc属性,此时只有在子类中通过super关键字调用的play函数可以读取abc的值
        console.log("A的构造函数中的原型方法");
    }
}
let a =new A();
console.log(a.play());
/*
A
undefined
A的构造函数中的原型方法
*/
class B extends A{
    constructor() {
        super();// 在子类的构造函数中调用了父类的构造函数
        this.abc="abc";

        super.def="def";//语句4
        console.log(super.def); // undefined

        /*super对象只能获取父类的原型属性和原型方法*/
        console.log(super.name);    //undefined
        console.log(super.age);     //undefined
        console.log(super.sex);     //男
        
        // super.show();   //报错
        //play是A的原型方法,可以通过super调用
        super.play();
    }
}

let b=new B();
console.log(b);			//B
let aa=new A();
console.log(aa);		//A

概念1:super关键字在非静态函数中,super的指向是父类的原型对象。

概念2:子类的非静态函数通过super调用父类方法时,这个方法中的this指向子类的实例对象。

概念3:所以在这种情况下,super和this在赋值的时候是等价的。

super关键字在静态方法中的含义

创建一个父类

class F{
    static name="爹";
    static show(){
        console.log(this);
        console.log(this.name);
        console.log("父级的静态函数");
    }
    show(){
        console.log("父级的普通函数");
    }
}

创建一个子类

super关键字在使用的时候必须显式的指定他是函数还是对象,要么super后面带括号,要么要使用‘.’运算符,如语句123。

子类的静态方法中通过super调用父类方法,调用到的是父类的静态方法,但是这个情况下,父类的静态方法中的this表示的是子类,而不是子类对象。

class S extends F{
    static name="儿子";
    static print(){
        // console.log(super); //报错		//语句1
        console.log(super.toString());	//语句2
        console.log(super.valueOf());	//语句3

        super.show();   //子类的静态方法中super关键字表示父类(F)
    }
    print(){
        super.show();   //子类的普通方法中super关键字表示父类的原型对象
    }
}

S.print();//通过类名调用静态方法

let s = new S();
s.print();//调用实例方法
S.print();//通过类名调用静态方法
/*
	class S extends F{
        static name="儿子";
        static print(){
            /*super关键字在使用的时候必须显式的指定他是函数还是对象,要么super后面带括号,要么要使用.运算符*/
            // console.log(super); //报错
            console.log(super.toString());
            console.log(super.valueOf());

            /*子类的静态方法中通过super调用父类方法,调用到的是父类的静态方法,但是这个情况下,父类的静态方法中的this表示的是子类,而不是子类对象*/

            super.show();   //子类的静态方法中super关键字表示父类(F)
        }
        print(){
            super.show();   //子类的普通方法中super关键字表示父类的原型对象
        }
    }
    
    class S extends F{
        static name="儿子";
        static print(){
            /*super关键字在使用的时候必须显式的指定他是函数还是对象,要么super后面带括号,要么要使用.运算符*/
            // console.log(super); //报错
            console.log(sup…
	class S extends F{
        static name="儿子";
        static print(){
            /*super关键字在使用的时候必须显式的指定他是函数还是对象,要么super后面带括号,要么要使用.运算符*/
            // console.log(super); //报错
            console.log(sup…
	儿子
    父级的静态函数                

*/
let s = new S();
s.print();//调用实例方法

//输出结果:父级的普通函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值