常见3种继承的优缺点

1,272 阅读2分钟

继承的3种优缺点

new执行过程
const person = new Person(args);
//相当于
const person = Person.new(args);
Function.prototype.new = function(){
       let obj = new Object();
       obj.__proto__ = this.prototype;
       const ret = this.apply(obj, arguments);
       return (typeof ret == 'object' && ret) || obj;
}
  1. 原型链继承
 	// (1) 父类 
        function Persion(name,age){ 
        	this.name = name; 
        	this.age = age; 
        }
        // 父类的原型对象属性 
        Persion.prototype.id = 10;
        // 子类 
        function Boy(sex){ 
        	this.sex = sex;
        }
        // 继承实现 
        Boy.prototype = new Persion('c5',27);
         var b = new Boy(); 
         alert(b.name)// c5 
         alert(b.id)//10
         
     // (2) 父类 
          function Parent(age) {
            this.name = ['2','4'];
            this.age = age;
          }
          // 父类的原型对象属性 
          Parent.prototype.getName = function(){
            return this.name     
          };
          // 子类 
          function Child(sex) {
            
          }
          Child.prototype = new Parent(23)
          var child = new Child();
          child.name.push('6');
          console.log(child.name);//["2", "4", "6"]
          console.log(child.getName());//["2", "4", "6"]
          var child2 = new Child();
          console.log(child2.name);//["2", "4", "6"]

优点:既继承了父类的模板,又继承了父类的原型对象。优点是继承了父类的模板,又继承了父类的原型对象,缺点就是父类实例传参,不是子类实例化传参,不符合常规语言的写法,而且引用类型的属性被所有实例共享(2)。

  1. 类继承(继承父类构造函数,但不继承父类的原型)避免了引用类型[m]的属性被所有属性共享;可以在Child向Parent传参。[经典继承] 缺点:方法只能在构造函数中定义,每次创建实例都会开辟空间给方法。
  function Parent(name, age) {
        this.name = name;
        this.age = age;
        this.m=["ghg",'ghjg','fghf']
      }
      // 父类的原型对象属性 
      Parent.prototype.getName = function () {
        return this.name
      };
      // 子类 
      function Child(sex,name,age) {
        Parent.call(this, name, age)
        this.sex = sex;
      }
      var child = new Child('女','xx',22);
      child.m.push('bhjb')
      // console.log(child.getName());// Uncaught TypeError: child.getName is not a function
      console.log(`性别:${child.sex}  姓名:${child.name} 年龄:${child.age}`);
      console.log(child.m);// ["ghg", "ghjg", "fghf", "bhjb"]
      
      // 性别:女  姓名:xx 年龄:22
      var child2 = new Child('女', 'xx', 22);
      // console.log(child.getName());// Uncaught TypeError: child.getName is not a function
      console.log(`性别:${child2.sex}  姓名:${child2.name} 年龄:${child2.age}`);
       // 性别:女  姓名:xx 年龄:22
      console.log(child2.m);// ["ghg", "ghjg", "fghf"] 
  1. 组合继承(原型链和经典) 解决引用属性实例共享和不能继承父类原型链上的属性;缺点:两次调用Parent构造函数
function Parent(name) {
        this.name = name;
        this.m=["ghg",'ghjg','fghf']
      }
      // 父类的原型对象属性 
      Parent.prototype.getName = function () {
        return this.name
      };
      // 子类 
      function Child(sex,name) {
        Parent.call(this, name)
        this.sex = sex;
      }
      Child.prototype=new Parent()
      var child = new Child('女','xx');
      child.m.push('bhjb')
      console.log(child.getName());// xx
      console.log(`性别:${child.sex}  姓名:${child.name} `);
      console.log(child.m);// ["ghg", "ghjg", "fghf", "bhjb"]
      
      // 性别:女  姓名:xx 年龄:22
      var child2 = new Child('女', 'xx');
      console.log(`性别:${child2.sex}  姓名:${child2.name} `);
          // 性别:undefined  姓名:xx 年龄:22
      console.log(child2.m);// ["ghg", "ghjg", "fghf"]  
  1. 后面再补组合继承
  2. ES6 class
 // class 实现类的继承
  class Parent{
    // 相当于构造函数
    constructor(name){
      this.name=name;
    }
    // 相当于原型
    sayName(){
      console.log(this.name);
    }
  }
  class Child extends Parent{
    // 相当于构造函数
    constructor(childName,age) {
      //  super相当于 把类的原型拿过来 
      //  以及Parent.call(this, childName)
      super(childName);
      this.age = age;
    }
    // 相当于原型
    getAge() {
      console.log(this.age);
    }
  }
  let a = new Child('daisy',24)
    a.sayName(); //汪某
    a.getAge(); // 24
// ES6 里面的class
/**注意两点:
 *  1. 在类中声明方法的时候,千万不要给方法加上function关键字
 *  2. 方法之间不用,;等任何符号
 * box.hasOwnProperty('nums')指实例上的属性,但是'nums' in box 表示在原型或者实例上能找到
 * 
 */
//ES6中 class 不存在变量提升
class Parent {
  constructor({name, age}){
    this.name=name;
    this.age=age;
  }
  say(){
    console.log(this.sex); 
  }
}
class child extends Parent{
  constructor({name, age,sex}) {
    // super 把类的原型 以及父对象中的this继承
    super({name,age});
    this.sex=sex
  }
  getAge(){
    console.log(this.age);
  }
}

var child1 = new child({name:'st',age:24,sex:'女'})
console.log(child1.name, child1.age, child1.sex); //st 24 女
child1.say();//女
child1.getAge(); //24