js继承方法

发布于:2025-05-30 ⋅ 阅读:(19) ⋅ 点赞:(0)

1、原型链继承

缺点:原型链属性公用,若实例A修改,也会影响实例B

           在创建 Child 的实例时,不能向 Parent 传参

 function children(){
     this.age = 17
 }
 function parent(){
     this.name = 'dawan'
 }
 children.prototype = new parent();
 const child = new children()
 console.log(child.age);
 console.log(child.name);

2、构造函数继承

缺点:继承实例属性时,实例对象的方法会占用多个空间,或者说,实例之间相同的方法被复制了一份, 而不是引用的同一个方法。 原因是我们用到构造函数,而方法都在构造函数中定义每次创建实例都会创建一遍方法, 造成内存浪费。

        // 构造函数继承
        // 父类
        function Animal(name, age) {
            this.name = name;
            this.age = age;
            this.colors = ['black', 'white'];
        }
        // 子类
        function Dog(name, age, breed) {
            Animal.call(this, name, age); // 核心:借用构造函数
            this.breed = breed;
        }
        // 使用
        const dog1 = new Dog('Buddy', 3, 'Golden');
        const dog2 = new Dog('Max', 2, 'Bulldog');
        console.log(dog1.name);   // Buddy
        console.log(dog1.breed);  // Golden
        // 验证引用类型不共享
        dog1.colors.push('brown');
        console.log(dog1.colors); // ['black', 'white', 'brown']
        console.log(dog2.colors); // ['black', 'white']

3、组合继承(构造函数继承+原型链继承)

缺点:组合继承会调用两次构造函数

        // 基本思想:书写构造函数继承,只不过把方法放在了原型上改进构造函数继承的弊端+调用了两次继承
        // 组合继承
        // 父类
        function Animal(name) {
            this.name = name;
            this.colors = ['black', 'white'];
        }
        Animal.prototype.eat = function () {           // -> 将方法放在原型上,解决了构造函数继承带来的会重复创建新的方法副本问题
            console.log(this.name + ' is eating');
        };
        // 子类
        function Dog(name, breed) {
            Animal.call(this, name); // 第一次调用:继承实例属性 -> 在每个实例上创建了独立的属性,解决原型链继承带来的引用类型共享的问题
            this.breed = breed;
        }
        Dog.prototype = new Animal(); // 第二次调用:继承原型方法
        Dog.prototype.constructor = Dog;
        Dog.prototype.bark = function () {
            console.log(this.name + ' is barking');
        };
        // 使用
        const dog1 = new Dog('Buddy', 'Golden');
        const dog2 = new Dog('Max', 'Bulldog');
        dog1.eat();  // Buddy is eating
        dog1.bark(); // Buddy is barking

4、寄生继承

 // 寄生继承的核心是工厂函数模式,直接返回一个对象,所以不需要new
        function createperson(name, age) {
            let obj = {
                name: name,
                age: age,
                sayhello: function () {
                    return `my name is${this.name}`
                }
            }
            obj.newfn = function () {
                return `my age is${this.age}`
            }
            return obj
        }
        const newperson =  createperson('dawan', 19);
        console.log(newperson.sayhello());
        console.log(newperson.name)
        console.log(newperson.age)
        console.log(newperson.newfn())

5、寄生组合继承

ES6 class 的底层实现就是这个继承方法

核心处理:将组合继承中第二次继承封装为了一个函数,在这个函数里实际通过new的时候调用的是空对象,无副作用。优化了组合继承的弊端

        // 寄生组合式继承
        // 核心函数
        function inheritPrototype(subType, superType) {
            function F() { } // 空函数,调用时不执行任何代码
            F.prototype = superType.prototype; // 只继承方法
            subType.prototype = new F(); // 调用空函数,无副作用        组合继承的第二步调用就调用了这里
            subType.prototype.constructor = subType;
        }
        // 父类
        function Animal(name) {
            this.name = name;
            this.colors = ['black', 'white'];
        }
        Animal.prototype.eat = function () {
            console.log(this.name + ' is eating');
        };
        // 子类
        function Dog(name, breed) {
            Animal.call(this, name); // 只调用一次
            this.breed = breed;
        }
        // 把组合继承的直接调用写成了这样
        inheritPrototype(Dog, Animal); // 寄生组合式继承
        Dog.prototype.bark = function () {
            console.log(this.name + ' is barking');
        };
        // 使用
        const dog1 = new Dog('Buddy', 'Golden');
        dog1.eat();  // Buddy is eating
        dog1.bark(); // Buddy is barking


网站公告

今日签到

点亮在社区的每一天
去签到