js 多种继承方案

javascript 多种继承方案

1. 原型链继承

  • 将父类的实例赋值给子类的原型对象 --> 实现原型链继承
    • 继承了 父类的实例上的属性方法 和 父类原型对象上的属性方法
    • 子类实例可以沿着原型链访问 父类私有属性方法 和 父类原型对象上的属性方法
	function Parent () {
	   this.x = '父亲'
	 }
	Parent.prototype.getX = function () {
	   console.log('父方法')
	}
	function Child () {
	   this.y = '孩子'
	}
	Child.prototype = new Parent()
	Child.prototype.constructor = Child // 让子类原型对象的constructor指回自己
	Child.prototype.getY = function () {
	   console.log('子方法')
	}
	let son = new Child()
	console.dir(son)
	console.dir(son.constructor) // 子类Child构造函数
	console.dir(Child.prototype.constructor) // 子类Child构造函数

2、call 继承

  • 在子类中将父类当做普通函数执行, 并将父类中的this改变成子类中的this
    • 子类是实例 继承了 父类实例的属性方法 为子类实例添加私有属性方法
    • 缺点:
      • 只能继承父类实例的属性和方法,不能继承父类原型对象上的属性方法
      • 无法实现复用,每个子类都有父类实例函数的副本,影响性能
	function Parent () {
	  this.x = 100
	}
	Parent.name = '张三'
	Parent.getAge = function () {
	  return 28
	}
	Parent.prototype.getX = function () { }
	Parent.prototype.age = 18
	function Child () {
	  //继承自Parent
	  Parent.call(this);
	  this.y = 200
	}
	var son = new Child();
	let parent = new Parent()
	console.dir(son);
	console.dir(parent);

3、组合继承。

+ 结合 call继承 和 原型继承组成 "组合继承"
+ 继承了 父类实例上的属性方法 和 父类原型对象上的属性方法
+ 组合模式的缺点:
  + 在使用子类创建实例对象时,其原型对象中会存在两份相同的属性方法。
	function Parent (name) {
	  this.name = name
	}
	Parent.prototype.sayName = function () { }
	function Child (name, age) {
	  Parent.call(this, name)
	  this.age = age;
	}
	Child.prototype = new Parent('王五')
	Child.prototype.constructor = Child;
	Child.prototype.sayAge = function () { }
	var son = new Child('张三', 29);
	console.dir(son);

4、寄生组合式继承[推荐写法]

  • 1 通过call继承 => 继承父类实例上的属性方法;
  • 2 将父类的原型对象 赋值 给子类原型对象 => 实现子类继承父类原型上的属性方法
  • 3 Child.prototype.constructor = Child 纠正子类constructor指向
  • 优点: 原型链还能保持不变, 因此,还能够正常使用instanceof 和 isPrototypeOf()
  • 这是最成熟的方法,也是现在库实现的方法
	function Parent (name) {
	  this.name = name
	}
	Parent.prototype.sayName = function () { }
	function Child (name, age) {
	  Parent.call(this, name)
	  this.age = age
	}
	Child.prototype = Object.create(Parent.prototype)
	Child.prototype.constructor = Child
	Child.prototype.sayAge = function () { }
	let son = new Child("张三", 18)
	console.dir(son)

5. 混入方式继承多个对象

  • Object.assign会把 Parent2 原型上的函数拷贝到 Child 原型上,使
  • Child 的所有实例都可用Parent2的方法。
	function Child () {
	  Parent1.call(this)// 继承 Parent1 实例的属性方法
	  Parent2.call(this)// 继承 Parent2 实例的属性方法
	}
	// 继承一个类
	Child.prototype = Object.create(Parent1.prototype)// 继承 Parent1 原型上的属性方法
	// 混合其它
	Object.assign(Child.prototype, Parent2.prototype)// 将Parent2原型上的属性方法合并到Child原型对象上; 实现继承Parent2原型上的属性方法
	// 重新指定constructor
	Child.prototype.constructor = Child
	Child.prototype.myMethod = function () { }

6. ES6中类的继承 extends [非常类似于寄生式组合继承]

  • 一旦使用 extends, 并且编写了 constructor, 必须在 constructor 函数第一行写上 super
  • 从原理上类似于 call 继承; super() ===> Parent.call(this)
	class Parent {
	  constructor (x) {
	    this.x = x
	  }
	  getX () { }
	}
	class Child extends Parent {
	  constructor (x) {
	    super(x)
	    this.y = 200
	  }
	  y = 200 // 不用 constructor 就不需要写 super
	  getY () { }
	}
	let ch = new Child(100)
	console.dir(ch);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值