美文网首页
整理面向对象的继承

整理面向对象的继承

作者: 小猪佩奇丶 | 来源:发表于2018-05-16 17:21 被阅读0次

阶段一

首先创建一个父类的函数方便继承

function Animal(aniamlType,age){
            this.aniamlType = aniamlType
            this.age = age
        }

然后再创建一个子类用来继承

function Dog(aniamlType, age, name) {
            Animal.call(this, aniamlType, age)
            this.name = name
        }

只需将this传进去执行一遍Animal函数,就能得到所有的属性了。
但是父类prototype的方法并不会被继承下来!

function Animal(aniamlType, age) {
        this.aniamlType = aniamlType
        this.age = age
    }
    Animal.prototype.eat = function () {
        console.log('eat')
    }
    function Dog(aniamlType, age, name) {
        Animal.call(this, aniamlType, age)
        this.name = name
    }
    var dog1 = new Dog('dog', '18', 'wb')
    dog1.eat()//Uncaught TypeError: dog1.eat is not a function

阶段二

由于父类的方法没办法继承,所以这时候我们就考虑从子类的prototype上来选择继承。这样就能让实例proto指向子类的prototype的时候能够得到父类的方法和属性了。
这时候我们将代码改一改

        function Animal(aniamlType, age) {
            this.play = ['eat','bite','shout']
        }
        Animal.prototype.eat = function () {
            console.log('eat')
        }
        function Dog(aniamlType, age, name) {
            this.aniamlType = aniamlType
            this.age = age
            this.name = name
        }
        Dog.prototype = new Animal()
        var dog1 = new Dog('dog', '18', 'wb')
        dog1.eat() //eat

可以看到这样就能让实例得到父类的方法了。
但是当我再创建一个实例的时候,然后修改父类的时候,由于两个实例的proto是子类的prototype,而子类的prototype引用同一个地址,即父类的实例(new Animal()),所以修改一个实例里面来自父类的对象的时候,另一个实例的那个对象也会跟着发生改变

        var dog1 = new Dog('dog', '18', 'wb')
        var dog2 = new Dog('dog', '20', 'wbd')
        dog1.play.push('owwwww')
        console.log(dog1.play)//["eat", "bite", "shout", "owwwww"]
        console.log(dog2.play)//["eat", "bite", "shout", "owwwww"]

这种方法虽然可以继承父类的方法,但是改变父类对象的时候,其他实例的这个对象也会跟着改变。

阶段三

上述两个阶段都有其可取之处,也有缺点。所以我们可以想到,应该能两者一起混合使用。于是就有了第三种方案了。

        function Animal(aniamlType, age) {
            this.aniamlType = aniamlType
            this.age = age
            this.play = ['eat', 'bite', 'shout']
        }
        Animal.prototype.eat = function () {
            console.log('eat')
        }
        function Dog(aniamlType, age, name) {
            Animal.call(this, aniamlType, age, name)//使用阶段一来继承属性
            this.name = name
        }
        Dog.prototype = new Animal()//使用阶段二来继承方法
        var dog1 = new Dog('dog', '18', 'wb')
        var dog2 = new Dog('dog', '20', 'wbd')
        dog1.play.push('owwwww')
        console.log(dog1.play)//["eat", "bite", "shout", "owwwww"]
        console.log(dog2.play)//["eat", "bite", "shout"]

这时候更改一个实例的时候就不会出现阶段三的问题了。
但是子类new,实例也要new一下,会增加性能损耗
于是想到直接等于让子类的prototype = 父类的prototype好了

        Dog.prototype = Animal.prototype

但是这时候问题又来了,子类在prototype上添加的方法会直接影响到父类的prototype,不方便别的子类继承该父类。而且子类的constructor会发生改变。

        Dog.prototype.cat = function () {
            console.log('cat')
        }
        console.log(Animal.prototype.cat) // function () { console('cat') }
        console.log(dog1.constructor)//function Animal ....

在上面会发现创建实例的竟然是爷爷,而不是爸爸。这就乱套了。
所以这时候就需要将子类的prototype复制父类的prototype而不是直接引用了。这时候不仅父类没有了方法,而且还可以直接修改子类的constructor了

        Dog.prototype = Object.create(Animal.prototype)
        Dog.prototype.cat = function () {
            console.log('cat')
        }
        Dog.prototype.constructor = Dog
        console.log(Animal.prototype.cat) //undefined
        console.log(dog1.constructor) //function Dog

这时候才是完美的面向对象的继承。
总结:
1.在子类内部继承属性
2.在子类的prototype上复制父类的prototype
3.更改子类prototype.constructor,让其指向自己。


更简单方便的方法,使用ES6的Class继承

        class Animal {
            constructor(aniamlType, age) {
                this.aniamlType = aniamlType
                this.age = age
            }
            eat() {
                console.log('eat')
            }
        }
        class Dog extends Animal {
            constructor(aniamlType, age, name) {
                super(aniamlType, age)
                this.name = name
            }
            cat() {
                console.log('cat')
            }
        }
        var dog1 = new Dog('dog', '18', 'wb')
        console.log(dog1.aniamlType, dog1.age, dog1.name)//dog 18 wb
        dog1.cat()//cat
        dog1.eat()//eat
        console.log(dog1.constructor) //class Dog extends Animal {...}

可以看出ES6的class不用那么复杂了。直接使用,没有后顾之忧

相关文章

  • 整理面向对象的继承

    阶段一 首先创建一个父类的函数方便继承 然后再创建一个子类用来继承 只需将this传进去执行一遍Animal函数,...

  • JavaScript之面向对象编程

    五、面向对象编程 目录:面向对象原型继承、面向对象class继承(ES6引入的) 1.面向对象原型继承 类:模板 ...

  • 王艳华Pythonday03

    Python的面向对象 Java 面向对象 继承

  • java基础-day10-面向对象4.0

    面向对象4.0 1. 面向对象之继承 1.1 生活中的继承 1.2 Java中的继承 1.3 子类对象创建,会调...

  • Python面向对象继承

    面向对象继承 面向对象编程 (OOP),英语全称:Object Oriented Programming,面向对象...

  • JAVA语言第二课

    JAVA面向对象——四大特征 继承篇——extendsJava 继承继承的概念继承是java面向对象编程技术的...

  • Web前端经典面试试题及答案2

    javascript面向对象中继承实现? 面向对象的基本特征有:封闭、继承、多态。在JavaScript中实现继承...

  • 面对对象高级编程

    面向对象高级编程: 面向对象编程:封装、继承和多态 面向对象高级编程:多重继承、定制类和元类

  • Objective-C初始化方法

    一、继承 面向对象的三大特性:封装,继承,多态。⾯向对象提供了继承特性。继承既能保证类的完整,又能简化代码。面向对...

  • JS汇总---面向对象&数组

    面向对象 js原型链的继承 静态属性怎么继承 js原型链以及特点 面向对象有哪几个特点 封装,继承,多态 对象的继...

网友评论

      本文标题:整理面向对象的继承

      本文链接:https://www.haomeiwen.com/subject/vycmdftx.html