JS实现继承的几种方式

原型链的续篇来了,如果不是太了解原型链朋友,可以先看下我的这篇博客,相信你会有所收获的~

构造继承

构造函数绑定

        function Animal(){
        this.species = '动物';
      }
        Animal.prototype.eat=function(){
            console.log('我是动物')
        }
        function Cat(name,color){
            Animal.call(this,arguments)
          this.name = name;
          this.color = color;
      }

缺点:

  • 无法继承原型的方法和属性
  • 每生成一个实例,就新开辟一块空间,浪费内存

prototype模式

        function Animal(){
        this.species = ['动物'];
      }
        Animal.prototype.eat=function(){
            console.log('我是动物')
        }
        function Cat(name,color){
          this.name = name;
          this.color = color;
      }
      Cat.prototype = new Animal();
      Cat.prototype.constructor = Cat;

缺点:

  • 实例共享同一个原型对象,如果父类是属性是引用类型,如上的species,则一个实例修改,那么另外一个也会改变,后续会演示~
  • 实例无法向父类构造函数传参

组合模式

        function Animal(){
        this.species = '动物';
      }
        Animal.prototype.eat=function(){
            console.log('我是动物')
        }
        function Cat(name,color){
            Animal.call(this,arguments)
          this.name = name;
          this.color = color;
      }
      Cat.prototype = Animal.prototype;
      Cat.prototype.constructor = Cat;

缺点:

  • Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到Animal.prototype

利用空对象作为中介

解决组合继承出现的问题

        function Animal(){
        this.species = ['动物'];
      }
        Animal.prototype.eat=function(){
            console.log('我是动物')
        }
        function Cat(name,color){
            Animal.call(this,arguments)
          this.name = name;
          this.color = color;
      }
      function extend(Child, Parent) {
        var F = function(){};
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.prototype.constructor = Child;
      }
        extend(Cat, Animal);

截止目前,prototype模式组合模式利用空对象作为中介,都有一个问题,那就是父类的原型属性如果是一个引用类型的话,一个实例改变其属性,其他实例的该属性均发生改变。比如Animal有一个type属性

	Animal.prototype.type = ['哺乳动物']

不管你用这三种的哪一种,去生成两个实例

	var cat = new Cat('小莉',  '红色')
	var cat1 = new Cat('大毛', '黄色');
	console.log(cat.type);  // ["哺乳动物"]
	console.log(cat.type); // ["哺乳动物"]
	cat.type.push('肉食动物');
	console.log(cat.type); // ["哺乳动物", "肉食动物"]
	console.log(cat1.type) // ["哺乳动物", "肉食动物"]

所以呢,prototype的属性尽量保持都是不变的变量~

非构造继承

Object继承

        function CreateObj(o){
            function F(){};  // 创建一个构造函数F
            F.prototype = o;
            return new F();
        }

以上也是Object.create的原理,可以直接用Object.create

	var info = {
		name: "hty",
		sex: 18
	}
	var newInfo = CreateObj(info)

浅拷贝

  function extendCopy(p) {
    var c = {};
    for (var i in p) { 
      c[i] = p[i];
    }
    return c;
  }

深拷贝

        function deepCopy(obj = {}) {
            if (typeof obj !=="object" || obj == null) {
                return obj
            }
            let result;
            if(obj instanceof Array) {
                result = []
            } else {
                result = {}
            }
            for(let key in obj) {
                result[key] = deepCopy(obj[key])
            }
            return result
        }

ES6继承

        class Animals {
            constructor(name){
                this.name = name
            }
            getName() {
                console.log(this.name)
            }
        }
        class Cat extends Animals {
            constructor(name){
                super(name)
            }
        }
        let cat = new Cat("小狗")

详细讲解,推荐大家去看阮老师的ES6

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值