前端学习(六十) JavaScript-class继承(javaScript)

继承

在说继承之前,先看在E5及以前是怎么做继承的,下例是最常用的组合继承

        function Co4(name,age){
            this.name=name;
            this.age=age;
        }
        Co4.prototype={
            constructor:Co4,
            sayName:function(){
                console.log(this.name)
            }
        }
        function Co4N(name,age){
            Co4.call(this,name,age) //将对象指向Co4,如果没有,那么会默认指向Obejct
        }
        Co4N.prototype=new Co4();
        Co4N.prototype.constructor=Co4;
        Co4N.prototype.sayAge=function(){
            console.log(this.age);
        }
        let ah=new Co4N("ddd",123)
        ah.sayAge()

在ES6中的类里面,用到了关键字extends,先看示例

            class da{}
            class da1 extends da{}

那么上面ES5中的写法,改成类的写法,如下例

            class da{
                constructor(name,age){
                    this.name=name;
                    this.age=age
                }
                sayName(){
                    console.log(this.name);
                    }
                sayAge(){
                    console.log(this.age);
                    }
            }
            class da1 extends da{
                constructor(name,age){
                    super();    //一定要写表面调用父级方法
                    this.name=name;
                    this.age=age;
                }
                sayAge(){
                    super.sayAge()
                }
                sayName(){
                    super.sayName()
                }
            }
            let da2=new da1('aaarac',20);
            da2.sayAge()    //20
            da2.sayName()   //aaarac

这边有几个注意点,子类必须在constructor中调用super方法,就跟ES5中Co4.call(this,name,age),指明this是指向的Co4以及Co4N.prototype.constructor=Co4指明构造函数是Co4一样

至于为什么一定要在constructor中定义super()方法,实际上,当我们将子类实例化以后da1虽然是继承(extends)自da,但是并没有将父类的this一起继承过来,而本身又没有this,所以会报错,因此要用super来将父类的this一起拿过来,而且,super()在constructor中一定要置顶写,因为上面也说了,子类本身没有this的,所以如果this.name=name写在super()之前,那么会报一个错误,大致就是找不到this

那么静态方法呢,设置super()之后,会不会继承过来,上一篇没有设置super之前,子类是无法访问父类的static也就是静态方法的,答案是肯定的,如下示例

            class Es6dd{
                constructor(){}
                static sayName(){
                   console.log("hehesayName");
                   return "he2he2say2Name";
                }
            }         
            class Es6dd1 extends Es6dd{
                constructor(name){
                    super();
                    this.name=name;
                }
                sayName(){
                    console.log(this.name);
                    console.log(super.sayName());
                }
            }
            let _es6dd=new Es6dd1('hehehe');
            _es6dd.sayName();   

判断子类是否来源于某个父类

Object.getPrototypeOf()方法,这样就可以判断子类的归属

console.log(Object.getPrototypeOf(Es6dd1) === Es6dd);    //true

super

在class中,super是一个非常重要的关键字,作用是继承父类里的属性和方法,super一共有两种用法

  • 当方法使用super()
  • 当关键字使用,super.xxx

当作方法使用时,也就是super()必须放在constructor里,否则会报错,例如

            class Es6e{
                constructor(){}
                fuc(){
                    super();    //报错
                }
            }

当作关键字使用时不能直接使用,如下例

            class Es6e{
                constructor(){
                    super(); 
                    console.log(super); //报错,super后面需要跟上其他关键字方法,以用来调用父级类的属性方法
                    }
            }

然后super可以在其他方法里使用,作用是调用父级元素的属性方法

            class Es6dd{
                constructor(){}
                static sayName(){
                   return "he2he2say2Name";
                }
                sayAge(){
                   return "123";
                }
            }         
            class Es6dd1 extends Es6dd{
                constructor(name,age){
                    super();
                    this.name=name;
                    this.age=age
                }
                static sayName(){
                    console.log(super.sayName());
                    //console.log(super.sayName === Es6dd.prototype.sayName);
                }
                sayAge(){
                    console.log(super.sayAge());
                }
            }
            Es6dd1.sayName()
            let _es6dd=new Es6dd1('hehehe');
            _es6dd.sayAge();   

注意:静态方法只能被静态方法调用,非静态方法只能访问非静态方法,不能是非静态方法访问静态方法

如果进一步对比,会发现super调用是完全对等的,也可以这么说super === 父类.prototype

console.log(super.sayName === Es6dd.prototype.sayName);    //true

进一步了解super

            class n{
                constructor(){
                    this.age = 18
                }
            }
            class n1 extends n{
                constructor(){
                    super();
                    console.log(this.age);  //18
                    this.age=6;
                    console.log(this.age);  //6
                    super.age=12;
                    console.log(super.age,this.age);    //undefined,12
                    
                }
            }
            let n1a=new n1();

第一个打印:在设置super后,n1本身没有this.age属性,那么这时打印的是原型链上父类的this.age

第二个打印:这里给this.age赋值了6,那么打印的时候自然就获得了6

第三个打印:在打印之前,这里不是用this.age赋值了,用了super.age赋值,这时的super等同于this,规范就是这么规定的,但是打印结果的时候super.age变成了undefined,是因为,这里的调用,super.age等同于了n.prototype.age,但是n没有age属性,所以打印成了undefined,我是这么理解的,赋值操作的时候,super等同与this,调用的时候等同于prototype。

detele不能删除通过super的父类

            class m{
                constructor(){}
                age(){return 18}
            }
            class m1 extends m{
                constructor(){
                    super()
                }
                age(){
                    console.log(super.age());
                    
                }
                delage(){
                    delete super.age();    //无效果
                }
            }
            let m1a=new m1();
            m1a.delage();
            m1a.age()

另一种extends

重申一下,ES6的class只是一种语法糖本质上和ES5原型对象没有什么区别,只是为了语法更简单更简洁

就是之前说的ES6的新方法,setPrototypeOf()

setPrototypeOf(a,b)就是将b设置成a的原型对象等同

  • a extends b
  • let a =new b()

猜你喜欢

转载自blog.csdn.net/zy21131437/article/details/81415189