js中的继承

原型继承

在这里插入图片描述

父类构造函数不能传参的问题

在这里插入图片描述
为什么不能给父类构造函数传递参数?

因为父类的构造函数是在我们写 Son.prototype = new Father(“父亲”) 时执行的,而且只执行一次,当我们创建子类实例时如 const son1 = new Son(10) ,父类构造函数是不执行的,所以父类构造函数中的属性就是所有子类实例所共享的属性,其实这也是原型的作用。正是由于在创建子类实例时父类构造函数并不会执行,所以我们没有必要给父类构造函数传递参数,直接在父类构造函数中定义就可以了。

为什么son1.name 和 son2.name 值不一样?

这个问题就牵扯出了属性的原型链查找和属性赋值的问题了

  1. 当我们进行属性的查找时是基于原型链查找的
  2. 当我们给属性赋值时,也会先通过原型链查找是否存在此属性,如果存在并且属性的 writable 为true,那也不会修改原型链上的属性值,而是在自己实例上创建新属性,因为原型链提供的是公共的属性和方法,如果每个实例都可以修改原型链上的属性,那原型对象将很难维护。所以当原型链上属性值为基本数据类型时(如:String,Number),这些值是不能被修改的,只会在自己的实例上修改或创建属性
  3. 如果原型上存在该属性但 writable 为 false,那么不管是原型还是子类实例都不能给该属性赋值
  4. 如果在原型上也没查找到该属性,则也会在子类实例上创建该属性

先去原型上查找,如果存在且writable为true:基本类型则在子类实例创建;引用类型则直接在原型上修改
如果原型上存在,但是writable为false:则在原型上和实例上都不能给该属性赋值

为什么son1.obj.city 和 son2.obj.city值一样呢?

js属性是基于原型链进行查找的,而我们通过 . (点语法) 就是在查找属性,而通过 =(等号) 是在给属性赋值。

  1. 当执行 son1.obj.city = “USA” 时,son1.obj先找到了原型上的obj对象,然后就基于obj对象开始了属性赋值,在赋值时就遵循了上个问题的流程
  2. 当执行 son2.obj.city = “China” 时,son2.obj也是先找到了原型上的obj对象,这个obj对象和son1.obj对象是同一个对象,在赋值时就会覆盖之前的值
  3. 当执行 son2.obj.sex = “woman” 时,son2.obj也是先找到了原型上的obj对象,然后发现obj对象中没有sex属性,则会创建sex属性并赋值为woman

所以当原型链上的属性值为Object、Array等引用类型时,那么当多个实例修改时,其实修改就是同一个对象

构造函数继承

在这里插入图片描述

共享原型

在这里插入图片描述

组合继承

call: 继承父类实例属性
原型链: 继承父类原型属性

  function Son(age) {
        Father.call(this);
        this.age = age;
        this.sleep = function () {
            console.log(this.name + "开始睡觉")
        };
    }

    Son.prototype = new Father();
    // Son.prototype = new Father().__proto__;
    // Son.prototype = Father.prototype;
    //让constructor再指向Son构造函数,否则会执行Father构造函数
    Son.prototype.constructor = Son;
    Son.prototype.playGame = function () {
        console.log(this.name + "开始玩游戏")
    };
    const son = new Son(10);

    console.log(son.name); //父亲
    console.log(son.age); //10
    console.log(son.hei); //200
    son.run(); //父亲开始跑步
    son.eat(); //父亲开始吃饭
    son.sleep(); //父亲开始睡觉
    son.playGame(); //父亲开始玩游戏

在这里插入图片描述
【优点:】

可以实现父类传参

【缺点:】

调用了两次父类

寄生组合继承

call:父类实例属性
Son.prototype = Object.create(Father.prototype);:父类原型属性

    function Son(age) {
        Father.call(this);
        this.age = age;
        this.sleep = function () {
            console.log(this.name + "开始睡觉")
        }
    }

    Son.prototype = Object.create(Father.prototype);
    Son.prototype.constructor = Son;
    Son.prototype.playGame = function () {
        console.log(this.name + "开始玩游戏")
    };
    const son = new Son(10);

    console.log(son.name); //父亲
    console.log(son.age); //10
    son.run(); //父亲开始跑步
    son.eat(); //父亲开始吃饭
    son.sleep(); //父亲开始睡觉
    son.playGame(); //父亲开始玩游戏

在这里插入图片描述
【优点:】

可以实现父类传参
只调用了一次父类,不会创建多余实例

临时构造函数继承

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值