JS中类的继承封装和多态

2020-02-28  本文已影响0人  空压机百科

子类继承父类的属性和方法(原生继承,call继承,寄生组合继承,ES6中class类继承)
原生继承:让子类的原型指向父类的一个实例

function A(){this.x = 100;}
A.prototype = {constructor: A, getX: function () {console.log(this.x);}};
function B(){this.y = 200;}
B.prototype = new A();
var f = new B();
原型图

1、方式:B.prototype = new A();A的实例本身具有父类A的私有属性和公有方法,子类B的原型指向它,那么子类B的实例就可以找到这些属性和方法
2、和传统后台语言继承不一样,子类继承父类,并不是把父类属性和方法克隆一份给子类,JS中的原型继承是让子类和父类建立原型链的机制。
存在问题:子类可以重写父类原型上的方法(重写),子类和父类还是有关系
父类的私有属性和公有属性都变为了子类实例的公有属性
子类原型上的属性和方法,重新执行父类实例后,之前的方法都没有了类的继承封装和多态

call继承:把父类A作为普通函数执行,让A中的 this 变为B的实例,相当于给B的实例增加一些属性和方法

function A(){this.x = 100;}
A.prototype = {constructor: A, getX: function () {console.log(this.x);}};
function B(){A.call(this);this.y = 200;}   //让A执行,让A中的this变为f
var f = new B();

存在问题:把父类A当作普通函数执行,和父类原型没关系,只是把A中的私有属性变为子类B实例的私有属性,A原型上的公有属性方法和B以及它的实例没有关系

寄生组合继承:A的私有变为B的私有,A的公有变为B的私有

function A(){this.x = 100;}
A.prototype = {constructor: A, getX: function () {console.log(this.x);}};
function B(){A.call(this);this.y = 200;}  //基于call把A的私有变为B的私有
//B.prototype = A.prototype;  //一般不这样处理,这种模式可以轻易修改父类原型的上的东西,会导致A的实例也受影响
B.prototype = Object.create(A.prototype);
var f = new B();
原型图

这种方法和原型继承的唯一区别:
B.prototype = new A() 创建的A的实例虽然指向了A的原型,但是实例中不是空的,存放了A的私有属性,这些属性成为了B的公有属性
B.prototype = Object.create(A.prototype)好处是创建了一个没有任何私有属性的空对象,指向A的原型,这样B的公有属性中不会存在A的私有属性
扩展:Object.create():内置Object类自带方法的作用:
1、创建一个空对象
2、让新建的空对象的__proto__指向第一个传递进来的对象(把传递进来的对象做为新创建的空对象的原型)

ES6中的类和继承:
ES6创建类标准语法,这种语法创建出来的类只能 new 执行,不能作为普通函数执行

class Fn{
    constructor(n,m) {
        // 等价于传统ES5类的构造体
        this.x = n;
        this.y = m;
    };
    getX(){}; // 给Fn的原型上设置方法(只能设置方法不能设置属性)
    static AA(){}; // 把Fn当作普通对象设置私有方法,不能设置属性
}
let f = new Fn(10,20);

继承方法:

class A{constructor() {this.x = 100;};getX(){}}
class B extends A{constructor() {super();this.y = 200;};getY(){}} // 类似于call继承,super中传递的实参都是给A的constructor传递
let f = new B()
上一篇下一篇

猜你喜欢

热点阅读