JS继承的六种方式

文章详细介绍了JavaScript中的六种继承方式,包括原型链继承、借用构造函数继承、组合继承、原型式继承、寄生式继承和寄生组合式继承,分析了各自的特性和优缺点,如原型链继承的单一继承特性,借用构造函数无法继承原型方法,以及寄生组合式继承在减少构造函数调用次数方面的改进。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、原型链继承

二、借用构造函数继承

三、组合继承(组合原型链继承和借用构造函数继承)

四、原型式继承

五、寄生式继承

六、寄生组合式继承


一、原型链继承

让新实例的原型是另一个构造函数的实例

        function Father(name: any) {
            this.name = name;
        }
        Father.prototype.getName = function () {
            console.log(this.name);
        };
        function Child(age: any) {
            this.age = age;
        }
        Child.prototype = new Father('zhangsan');
        const child = new Child('12');
        console.log(child.name); // zhangsan
        child.getName();
  • 特点:新实例可继承的属性:实例的构造函数的属性、父类构造函数的属性、父类原型的属性 
  • 缺点:继承单一

二、借用构造函数继承

        function Father(name: any) {
            this.name = name;
        }
        Father.prototype.getName = function () {
            console.log(this.name);
        };

        function Child(name: any) {
            Father.call(this, name); //使用call 使得构造函数Father的this指向了Child
        }
        const child = new Child('lisi'); //lisi
        console.log(child.getName()); //child.getName is not a function 没有继承父类原型上的方法
  • 特点:只继承了父类构造函数的属性,没有继承父类构造函数的原型,可以给父类构造函数传参
  • 缺点:只能继承父类构造函数的属性,每实例化一个薪实例,就会调用一次父类构造函数 

三、组合继承(组合原型链继承和借用构造函数继承)

        function Father(name: any) {
            this.name = name;
        }
        Father.prototype.getName = function () {
            console.log(this.name);
        };

        function Child(name: any) {
            Father.call(this, name); //使用call 使得构造函数Father的this指向了Child
        }
        Child.prototype = new Father('lisi'); //lisi
        const child = new Child('zhangsan');
        console.log(child.name); //zhangsan
        child.getName(); //zhangsan
  • 特点: 结合1,2两种继承方法,原型链继承原型上的属性和方法,而通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性
  • 缺点:调用了两次父类构造函数,在子类借用构造函数继承时调用了一次,父类实例化的时候调用了一次

四、原型式继承

       function child(obj: any) {
            function F() {}
            F.prototype = obj; //obj为父类的实例对象 相当于F的原型对象指向父类的实例对象
            return new F(); //实例化了F 返回了F的实例对象
        }

        let obj = {
            name: 'lhhh',
            age: 18,
            like: ['a', 'b'],
            showName() {
                console.log('my name is:', this.name);
            },
        };

        const newChild = child(obj); //实例对象上不存在name 根据原型链往_proto_上找 找到了name
        const newChild2 = child(obj); //实例对象上不存在name 根据原型链往_proto_上找 找到了name
        newChild.name = 'httt';
        newChild.like.push('c');
        console.log(newChild); //like变为[a,b,c] name:'httt'
        console.log(newChild2); //like变为[a,b,c]  name:'lhhh'
  • 特点:相当于复制一个对象, 用函数进行包装
  • 缺点:引用类型的数据,一个子实例修改后,会导致所有的子实例的该数据都被修改。

五、寄生式继承

        function child(obj: any) {
            function F() {}
            F.prototype = obj; //obj为父类的实例对象 相当于F的原型对象指向父类的实例对象
            return new F(); //实例化了F 返回了F的实例对象
        }

         //寄生式继承
        function changeData(obj: any) {
            const newData = child(obj);
            newData.age = 23;
            return newData;
        }

        let obj = {
            name: 'lhhh',
            age: 18,
            like: ['a', 'b'],
            showName() {
                console.log('my name is:', this.name);
            },
        };

        const childInfo = changeData(obj); //经过这一步 函数变成了可以增删改的对象
        console.log(childInfo);
  • 特点:将最终结果改为了一个对象,对象可以进行增删改 

六、寄生组合式继承

  //创建父类
        function Father(name: any) {
            this.name = name;
        }

        //在父类原型上增加方法
        Father.prototype.getName = function () {
            console.log(this.name);
        };

        //创建子类
        function Child(name: any) {
            Father.call(this, name);
        }

        //新创建的对象保持指向Father的原型对象
        Child.prototype = Object.create(Father.prototype);
        const child = new Child('zhangsan');
        child.getName(); //zhangsan
  • 缺点:仍然调用了两次父类构造函数,这是组合式继承的通病
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值