JS基础---继承(原型继承、构造函数继承、组合继承、拷贝继承、寄生继承、寄生组合式继承)

JS基础之继承

继承 一个实例想要试用父亲构造函数的属性和方法

一、继承方法之原型继承

// 准备父类
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.eat = function(){
            console.log('eating')
        }
        /*
            Student.prototype = {name: 'tom', age: 20, __proto__:Person.prototype}
            继承方法之原型继承
                - 通过改变原型链的方式实现继承
                - 核心思路 父亲的实例作为子类的prototype
                - 好处 可以实现继承父亲的属性和父亲原型伤的
                - 缺点 传参分开传、继承的属性不在自己的实例上
        */
        // 子类
        function Student(name,age,sex){
            this.sex = sex;
        }
        Student.prototype = new Person('Leo',20);
  
        var s = new Student('man');
      
        console.log(s)

二、继承方法之构造函数继承

// 准备父类
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.eat = function(){
            console.log('eating')
        }
        /*
            Student.prototype = {name: 'tom', age: 20, __proto__:Person.prototype}
            继承方法之借用继承(构造函数继承)
                - 构造函数继承
                - 核心思路 在子类的构造函数中,使用父类的构造函数.call(this,...)
                - 好处 继承的属性在自己实例上,传参不需要分开传
                - 缺点 父类的原型上的内容不能继承
        */
        // 子类
        function Student(name,age,sex){
            this.sex = sex;
            // Person也是函数。可以直接调用,直接调用Person函数中的this是window
            // 通过call调用弗雷构造函数,并且改变Person函数中的this的指向为student实例
            Person.call(this,name,age)
        }
        Student.prototype = new Person();
        Student.prototype.study = function(){
            console.log('studing')
        }
        var s = new Student('Leo',20,'man');
        s.eat();
        console.log(s)

三、继承方法之组合继承

// 准备父类
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.eat = function(){
            console.log('eating')
        }
        // 子类
        function Student(name,age,sex){
            this.sex = sex;
            // Person也是函数。可以直接调用,直接调用Person函数中的this是window
            // 通过call调用弗雷构造函数,并且改变Person函数中的this的指向为student实例
            Person.call(this,name,age)
        }
        Student.prototype = new Person();// {name:undfined,age:undfined,__proto__:Person.prototype}
        Student.prototype.study = function(){
            console.log('work hard')
        }
        Student.prototype.constructor = Student;
        /*
            Student.prototype = {name: 'tom', age: 20, __proto__:Person.prototype}
            继承方法之借用继承----组合继承
                - 原型继承+借用继承
                - 核心思路 
                - 好处 继承的属性在自己实例上,传参不需要分开传;父类的原型上的内容能继承
                - 缺点 子类的constructor指向的是父类
        */
       
        var s = new Student('Leo',20,'man');
        s.eat();
        s.study();
        console.log(s);

四、继承方法之拷贝继承--for in

// 准备父类
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.eat = function(){
            console.log('eating')
        }
        // 子类
        function Student(name, age, sex){
            this.sex = sex;
            var p = new Person(name, age)
            for(var k in p){
                Student.prototype[k] = p [k]
            }
        }
        /*
            Student.prototype = {name: 'tom', age: 20, __proto__:Person.prototype}
            继承方法之拷贝继承
                - for in继承
                - 核心思路 对一个父亲实例,然后对其for in 把父实例及其原型的内容复制给子类的原型上
                - 好处 传参不需要分开传;父类的属性和原型上的内容能继承,constructor正常指向
                - 缺点 继承的属性不在自己的实例上,不能继承不能被枚举的属性,会一直遍历到Object.prototype
        */
        Student.prototype = new Person('tom',20,"男")
        var s = new Student('man');
        console.log(s)

五、继承方法之寄生继承

// 准备父类
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.eat = function(){
            console.log('eating')
        }
				// 寄生继承-寄生实例
        // 子类
        function Student(name, age, sex){
            this.sex = sex;
            var p = new Person(name, age)
            return p;
        }
        /*
            Student.prototype = {name: 'tom', age: 20, __proto__:Person.prototype}
            继承方法之寄生继承
                - 寄生实例
                - 核心思路 var p = new Person(name, age); return p;
                - 好处 父亲的属性或原型东西都可以继承
                - 缺点 new 子类的时候没有自己的的属性和自己原型的东西
        */
        var s = new Student('tom',20,"男");
        console.log(s)
        console.log(s instanceof Person) // true

				// 寄生继承-寄生原型
        // 子类
        function Student1(name, age, sex){
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
        Student1.prototype = Person.prototype;
        Student1.prototype.study = function(){
            console.log('work hard')
        }
        /*
            Student.prototype = {name: 'tom', age: 20, __proto__:Person.prototype}
            继承方法之寄生继承
                - 寄生原型
                - 核心思路 Student1.prototype = Person.prototype;
                - 好处 父亲的属性或原型东西都可以继承,自己的属性或方法都可以添加
                - 缺点 父亲属性不能被继承,此外修改子类原型,父类实例也受影响
        */
        var s1 = new Student1('tom',20,"男");
        s1.eat();
        s1.study();
        console.log(s1)

六、继承方法之寄生组合式继承

借用继承+寄生继承+原型继承+第三方构造函数
// 准备父类
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.eat = function(){
            console.log('eating')
        }
        // 寄生组合式继承
        // 子类
        function Student(name, age, sex){
            this.sex = sex;
            // 借用继承 实现继承父类的属性
            Person.call(this,name, age)
        }
        (function(){
            function A(){
            }
            A.prototype = Person.prototype; // 寄生原型
            // var a = new A(); //a实例能够继承Person原型的东西
            // Student.prototype = a; // a==={__proto__: Person.prototype} 原型继承
            Student.prototype = new A();
        })();
        
        Student.prototype.love = function(){
            console.log('loving')
        }
      
        var s = new Student('tom',20,"男");
        console.log(s)// {name: 'tom',age:20,sex:'男',__proto__: {__proto__:Person.prototype}}
        s.eat();
        /*
            Student.prototype === new A()
            A.prototype === Person.prototype
            s.__proto__ 
        */
        
posted @ 2021-04-22 18:04  春燕啄春泥  阅读(114)  评论(0编辑  收藏  举报