js继承

586 阅读2分钟

js的继承方法:

1.原型链继承

function Parent(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.arr = [1,2,3]
}
Parent.prototype = {
    init:function () {
        console.log(this)
    }
}
function Child(weight) {
    this.weight = weight;
}
Child.prototype = new Parent('ljy',18,'男');
var a = new Child(10);
a.arr.push(4);
console.log(a);
// 控制台打印:
Child {weight: 10} 
    weight: 10 
    __proto__: 
        age: 18 
        arr: (4) [1, 2, 3, 4] 
        name: "ljy" 
        sex: "男" 
        __proto__:
             init: ƒ () 
            __proto__: Object
var b = new Child(20);
console.log(b);
// 控制台打印
Chid {weight: 10} 
      weight: 10     __proto__: 
        age: 18 
        arr: (4) [1, 2, 3, 4] 
        name: "ljy" 
        sex: "男" 
        __proto__:
             init: ƒ () 
            __proto__: Object

缺点:

    1.Child.prototype = new Parent('ljy',18,'男');这儿如果传了参数,会导致后续实例都有这3个属性
    2.对原型属性的修改会影响后面所有

2.构造函数继承

function Parent(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
}
Parent.prototype = {
    init:function () {
        console.log(this)
    }
}

function Child(weight) {
    // 继承
    Parent.call(this);
    this.weight = weight;

}

var a = new Child(10);
console.log(a);

缺点:1.无法继承原型上的方法属性

3.组合继承

function Parent(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.arr = [1,2,3]
}
Parent.prototype = {
    constructor:Parent,
    init:function () {
        console.log(this)
    }
}
function Child(name,age,sex,weight) {
    Parent.call(this,name,age,sex);
    this.weight= weight;
}
Child.prototype =  new Parent();
Child.prototype.constructor = Child;
console.log(Child.prototype.constructor)
var a = new Child('ljy',18,'男',100);
console.log(a);
控制台:   Child {name: "ljy", age: 18, sex: "男", arr: Array(3), weight: 100}            age: 18
            arr: (3) [1, 2, 3]
            name: "ljy"
            sex: "男"
            weight: 100
            __proto__: Parent
                age: undefined
                arr: (3) [1, 2, 3]
                init: ƒ ()
                name: undefined
                sex: undefined
                __proto__:
                    constructor: ƒ Parent(name,age,sex)
                    init: ƒ ()
                    __proto__: Object

优点:
    1.解决了原型链上属性一设置影响所有的问题(其实是增加了实例属性,原型属性依然存在,
                    只是我们设置的时候,如果实例拥有此属性,则不向上寻找原型属性)
    2.解决了原型方法的复用

4.寄生组合继承

function Parent(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.arr = [1,2,3]
}
Parent.prototype = {
    constructor:Parent,
    init:function () {
        console.log(this)
    },
    getList:function () {
        
    }
    
}
function Child(name,age,sex,weight) {
    Parent.call(this,name,age,sex);
    this.weight= weight;
}
// Child.prototype.__proto__ = Parent.prototype;
/*
* 我的第一想法是:Child.prototype. = Parent.prototype;
* 因为上面的组合继承虽然已经很好了,但是它会调用两次Parent()
* 组合继承方法的缺点:在Child原型中声明了Parent实例的属性,在Child实例中也声明了Parent实例的属性,造成内存浪费
* Child.prototype = Parent.prototype;这个方法可以完全解决实例重复问题,因为Child.prototype指向的是Parent.prototype,
* 并不像之前是指向Parent的实例
* 但是,有如下问题:如果修改了Child.prototype的值,势必会引起Parent.prototype变化,如何解决问题呢?
*
* 方法: 声明一个中间方法就好了
* function Create(obj){
*   var f = function(){};
*   f.prototype = obj;
*   return new f()
* }
* var basicObj =  Create(Parent.prototype);
* basicObj.constructor = Child;
* Child.prototype = Create(Parent.prototype)
*
* 上述代码就解决了上述问题
* */
function Create(obj){
   var f = function(){};
   f.prototype = obj;
   return new f()
}
 var basicObj =  Create(Parent.prototype);
 basicObj.constructor = Child;
 Child.prototype = basicObj
var a = new Child('ljy',18,'男',100);
console.log(a)
a.init();