构造函数与类的继承及原型链

构造函数的继承:三种

第一种:原型链继承(会将引用类型的值修改)

就是将父构造函数的实例赋给子构造函数的原型

        //父构造函数        
        function Person() {
            this.uname = 'zs';
            this.fruits = ['苹果','桃子','橘子']
            this.run = function() {
                console.log(this.uname+'跑了');
            }
        }
        // 子构造函数
        function Star(id) {
            this.id = id
        }
        //将子构造函数的原型指向父构造函数的实例
        Star.prototype = new Person()

        let Dlira = new Star()
        console.log(Dlira.uname);
        Dlira.run()
        console.log(Dlira.fruits);
        Dlira.uname = 'li';     
        Dlira.fruits.push('香蕉')     
        console.log(Dlira.fruits);    //['苹果','桃子','橘子','香蕉']
        let taile = new Star()
        console.log(taile.uname);
        console.log(taile.fruits);    //['苹果','桃子','橘子','香蕉']
        console.log(taile.fruits === Dlira.fruits);     // true

第二种       call()继承(浪费内存)

通过 call()更改this指向

        function Person() {
            this.uname = 'zs';
            this.fruits = ['苹果','桃子','橘子'];
            this.run = function() {
                console.log(this.uname+'跑了');
            }
        }
        Person.prototype.sing = function() {
            console.log('ahahah');
        }
        function Star(id) {
            this.id = id;
            Person.call(this);
        }
        // false  每实例一个对象,都会拷贝构造函数上的属性和方法挂载到实例对象上,浪费内存
        let Dlira = new Star();
        console.log(Dlira.uname);
        console.log(Dlira.fruits);    //['苹果','桃子','橘子']
        Dlira.fruits.push('石榴')
        console.log(Dlira.fruits);    //['苹果','桃子','橘子','石榴']
        let taile = new Star();
        console.log(taile.fruits);    //['苹果','桃子','橘子']
        console.log(Dlira.fruits === taile.fruits);  false
        Dlira.sing()  

第三种 组合继承,将第一种和第二种合起来

        function Person() {
            this.uname = 'zs';
            this.fruits = ['苹果','桃子','橘子'];
            this.run = function() {
                console.log(this.uname+'跑了');
            }
        }
        Person.prototype.sing = function() {
            console.log('ahahah');
        }
        Star.prototype = new Person()
        // 因为 改变了Star.prototype的指向,导致没有了 constructor,因此我们要将    Star.prototype.constructor重新指向Star
        Star.prototype.constructor = Star
        function Star(id) {
            this.id = id;
            Person.call(this);
        }
        let Dilra = new Star();
        Dilra.fruits.push('莲雾');  
        console.log(Dilra.fruits);  //['苹果','桃子','橘子','莲雾']
        let TaiLe = new Star();
        console.log(TaiLe.fruits);  //['苹果','桃子','橘子']
        console.log(Dilra.sing === TaiLe.sing);     // true

ES6 类的继承

es6 是通过 关键字extends 实现继承的

        class Father {
            constructor(uname,age) {
                this.uname = uname;
            }
            run() {
                console.log(this.uname+'跑了');
            }
        }
        class Son extends Father {  

        }
        const son1 = new Son('son1');
        console.log(son1.uname);    // son1
        son1.run()  // son1跑了
        class Dau extends Father {
            constructor(uname,sex) {
                // super() 当我们要给子类添加其他的属性时,就要用super()拿到父类的属性和方法,如果不加super(),就会报错
                super(uname);
                this.sex = sex;
            }
        }
        const dau = new Dau('Dilra','女');
        console.log(dau.uname,dau.sex);     //Dilra  女
        dau.run()   // Dilra跑了

原型链:每个实例对象都有一个__proto__属性,它指向其构造函数的原型对象;因为原型对象也是一个对象,所以它也有__proto__属性,因此它也指向它的构造函数的原型对象。因此,当我们去调用一个对象的属性或方法时,先会在其自身上寻找,如果找不到,就要通过它的__proto__所指向的原型对象上去寻找,如果还没有,就通过原型对象的__proto__所指向的其构造函数的原型对象上寻找,直到找到或者返回undefined,这就是原型链。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值