每次遇到JS面对对象这个概念,关于继承及原型,脑海里大概有个知识框架,但是很不系统化,复习下,将其系统化,内容涉及到对象的创建,原型链,以及继承。

创建对象

两种常用方式,其余的比较少见
工厂模式:


    function createObject(){
        var o = {}
        o.name = "Nico"
        o.age = 8
        o.sayName = function(){
            alert(this.name)
        }
        return o
    }

这种方式比较不开门见山,比较直接的事第二种,构造函数方式

    function Object(name, age){
        this.name = name
        this.age = age
        this.sayName = function(){
            alert(this.name)
        }
    }

通常使用第二种,比较直观
考虑到函数也是对象的一种,每次对象的实例化中其方法也会跟随着实例化一次,为了解决这个问题,因此出现了组合构造原型模式,这是最常用的一种方式。

组合构造原型模式


     function Object(name, age){
        this.name = name
        this.age = age
    }
    
    Object.prototype.sayName = function(){
        alert(this.name)
    }

将自身属性于构造函数中定义,公用的方法绑定至原型对象上

原型对象的解释
每一个函数创建时本身内部会有一个固有的原型对象,可以通过 函数名.prototype 去访问,而其原型对象又有一个属性constructor指针指向该函数。
假设有一个构造函数

   function Person(){
        this.name = "Nicholas"
        this.age = 29
        this.job = "Software Engineer"
    }
    
    Person.prototype.sayName = function(){
        alert(this.name)
    }
    var person1 = new Person()
    var person12 = new Person()

其原型对象、构造函数、实例之间的关系如下图片描述

构造函数可以通过Person.prototype来访问原型对象,但是实例是没有办法来访问原型对象的,但是在Firefox、Chrome、Safari的每一个实例对象都有一个_proto_的属性进行访问其原型

继承

原型链:
根据以上的原型关系可以发现,实例先从自身定义的属性及方法中取值,若无法寻找到,则向上一级即原型对象访问需要的属性及方法,若其原型对象是另一个对象的实例,仍无法访问到属性与方法的话,再继续向该实例的原型对象访问,这样就构成了一个原型链,也是继承的实现方式。

有如下两个对象

    function SuperType(){
            this.property = true
        }

        SuperType.prototype.getSuperValue = function(){
            return this.property
        }

        function SubType(){
            this.subproperty = false
        }

        SubType.prototype = new SuperType()

        SubType.prototype.getSubValue = function(){
            return this.subproperty
        }

        var instance = new SubType()

        alert(instance.getSubValue()) // false
  

这是一个简单的继承实现方式,子类SubType具有了父类的property属性,同时也具有getSubValue的方法。
其原型链如下:
图片描述

但是这样做会将父类的属性绑定至子类的原型上,如果父类具有按引用访问的数据时,子类的某一个实例中该数据的变化会导致所有子类实例该数据的变化,因此改进为借用构造函数模式的继承

        function SubType(){
            SuperType.call(this)
            this.subproperty = false
        }

这样就解决了该问题,将property属性定义在了子类构造函数上,子类实例访问时先从该本身构造函数具有的属性中进行访问,且进行操作,相当于覆盖了原型上的该同名属性。

但是上述的方法又出现了一个别的问题,该问题也比较容易解决,比较少用到,笔记先到这,后续笔记将记录该问题及解决办法


jiejiewu
13 声望0 粉丝