JS-04何为继承以及实现方式

目录

1 JS中继承的概念

2 为什么要使用继承?-解决内存浪费

2.1 问题引入

2.2 问题解决

2.3 拓展

 3 继承的实现方式

3.1 原型链继承 1

3.2 原型链继承 2


JS中继承的概念

        通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法,我们把这种方式称之为继承  `并不是所谓的xxx extends yyy`

2 为什么要使用继承?-解决内存浪费

2.1 问题引入

        有些对象会有方法(动作、行为),而这些方法都是函数,如果把这些方法和函数都放在构造函数中声明就会导致内存的浪费🍂


    function Person(){
        this.say=function(){
            console.log("你好")
        }
    }
    var p1=new Person();
    var p2=new Person();
    console.log(p1.say === p2.say);   //false

现象:两个实例的say方法不相等,控制台输出为false

结论:若将方法放入构造函数中,则当每创建一个实例时就会再次创建结构相似的方法。这两个方法不是同一个。所以会造成内存的浪费

2.2 问题解决

🍃解决方案:把say方法写在他们共同的(父对象)中 

 function Person(name,age){
        this.name=name;
        this.age=age;
        this.say=function(){}
    }
    var p1=new Person();
    var p2=new Person();
    
    //p1对象和p2对象的say方法是否是同一个方法:false
    console.log(p1.say===p2.say);

    //由于say方法可能功能相似,但是不是同一个方法(没有指向同一块内存,会造成内存浪费)
    //解决方案:把say方法写在他们共同的(父对象)中
    //其实他们共同的父对象,就可以通过:Person.prototype来获取

    //-->只要把say方法写在Person.prototype中,那么say方法就是同一个方法
    Person.prototype.run=function(){
        console.log('时速555KM');
    }
    //此时p1和p2都可以访问到run方法
    p1.run();
    p2.run();
    //验证p1.run和p2.run是否是同一个方法?
    console.log(p1.run == p2.run); //指向同一个方法,这种方法避免了内存的浪费
    
    console.log(p1.run == Person.prototype.run);
    //true

    var p3=new Person();
    console.log(p3.run == p1.run); //true
    console.log(p3.run === p1.run);//true

 🌸结论:只要往某个构造函数的prototype对象中添加某个属性、方法,那么这样的属性、方法都可以被所有的构造函数的实例所共享

==>这里的【构造函数的prototype对象】称之为原型对象

Person.prototype是 p1 p2 p3 的原型对象

Person.prototype是Person构造函数的【实例】的原型对象

2.3 拓展

猜猜看?

Person的原型对象是谁呢?

  1. 首先要知道Person的构造函数:Function
  2. 所以Person的原型对象是:Function.prototype

p1的原型对象是谁呢?

  1. 首先要知道p1是谁创建的? Person
  2. 所以p1的原型对象时:     Person.prototype

 3 继承的实现方式

3.1 原型链继承 1

代码片实现,如下:

<script>
    function Dog(){

    }
    var d1=new Dog();
    //为了让d1有一个叫的方法,
    //不行:d1.say=function(){}
    //正确:在原型中添加方法
    Dog.prototype.say=function(){
        console.log('汪汪汪');
    }
</script>

🍂缺点:添加1、2个方法无所谓,但是如果方法很多会导致过多的代码冗余。代码片如下:

    function Cat(name){
        this.name=name;
    }
    var tom=new Cat("汤姆");//实例
    //目的:把say方法放在tom的原型对象中(Cat.prototype)
    Cat.prototype.say=function(){}

    //问题:
    Cat.prototype.s1=function(){}
    Cat.prototype.s2=function(){}
    Cat.prototype.s3=function(){}
    Cat.prototype.s4=function(){}
    Cat.prototype.s5=function(){}
    //通过上面的方式,给tom的原型对象添加了好多方法,也就是让tom拥有了好多方法,但是代码产生了不少的冗余(重复)

3.2 原型链继承 2

🍃解决上面问题代码冗余问题,改良版思路:

   //-->为了减少这种重复,改良版:
    Cat.prototype = {
        a1:function(){},
        a2:function(){},
        a3:function(){},
        a4:function(){},
        a5:function(){}
    }
    console.log(tom.s1);    //可以访问
    console.log(tom.a1);    //undefined
    

        原因:tom对象在创建的时候已经有了一个确定的原型对象,就是旧的Cat.prototype由于Cat.prototype后面被重新赋值,但是tom对象的原型对象却没有改变,所以tom对象并不能访问到新原型对象中的a1-a5方法

 如何解决这个问题?
 -->先改变原型、再创建对象

🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀

    Person.prototype={
        constructor:Person,
        say:function(){
            console.log("你好");
        },
        run:function(){
            console.log("正在进行running");
        }
    }

+ 注意点:
+ a、一般情况下,应该先改变原型对象,再创建对象
+ b、一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构

<script>
    function Tiger(){

    }
    Tiger.prototype={
        a:function(){
            
        },
        b:function(){

        }
    }
    //创建tiger实例,此时的tiger实例的原型对象是新原型,所以tiger可以访问到新原型中的属性和方法(a/b)
    var tiger=new Tiger();
    console.log(tiger.a);
    console.log(tiger.b);
</script>

🐶其他继承实现方式(拷贝继承、原型式继承、借用构造函数实现继承),后续将会继续发布分享,敬请期待!! 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸爬打滚的小M

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值