对象构造函数模式与继承

89 阅读3分钟

引言

上篇文章已经提到过创建对象的方式:

  1. 通过Object来创建对象
  2. 通过字面量来创建对象
  3. 通过一些模式来实现接口,更方便的创建对象

说到模式要存在很多模式:

  1. 工厂模式
  2. 构造函数模式
  3. 原型模式
  4. 组合使用构造函数模式和原型模式
  5. 动态原型模式
  6. 寄生构造函数模式
  7. 稳妥构造函数模式

构造函数模式

它会将属性和方法都定义在构造函数的内部

function Student(name,age){
    this.name=name;
    this.age=age;
    this.test=function(){
        alert('haha")
    }
}

var student1=new Student(xxx,yyy)
alert(student1.constructor==Student  )         //true
alert( student1 instanceof Student    )        //true

//构造函数弥补了工厂模式难以确定对象类型的缺点

在ECMAScript中每一个方法实例都是Fountion的实例对象

当然这种构造函数模式是存在缺点的,因为构造函数内部定义的每一个方法会在每创建一个新对象时就会占用一块内存 这是很不合理的因为方法是每个对象都相同的,实在没必要创建那么多次

原型模式&组合使用构造函数模式和原型模式

首先要知道什么是原型对象 : 每当创建一个函数(对象)它默认都会有一个属性prototype这个属性指向这个函数的原型对象

原型对象中也有一个constrouctor属性指回这个函数,每个函数的实例中都有一个 _proto_属性指向它所属类型的原型对象 虽然每个函数中都存在原型对象,但一般都会在构造函数中使用它把它当成一个公共资源共享区:即所有实例都能访问到的

在这个prototype原型对象中就可以存放那些所有对像共有的属性或方法,而把那些需要自己设置的属性放在构造函数内部,这就是组合使用构造函数模式和原型模式

每一个实例对象都可以通过内部的_proto_访问到原型对象中的属性或方法,所以当对象调用的属性或方法在原型中是可以访问到的

当一个实例对象调用属性或方法时会先在自己实例中寻找,再去原型中查找,如果原型中不存在就回去父类的原型中查找

继承

构造函数的继承主要考虑两点:

  1. 如何继承父类构造函数内部的属性
  2. 如何继承父类原型对象中的属性和方法

继承父类构造函数内部的属性

function Father(name){
    this.name=name
}

function son(name,age){
    Father.call(this,name)
    this.age=age
}

通过call方法调用父类的构造函数并改变内部的this指向,并传入参数 此时调用的父类构造方法的this指向了子类的实例,就为子类的实例添加父类中存在的属性并为属性赋值

何继承父类原型对象中的属性和方法

首先把父类的实例对象赋值给构造函数的原型对象 把父类实例中添加constructor属性指回子类构造函数

function Father(name){
    this.name=name
}

Father.prototype.show=function(){
        alert("haha")
   }

function son(name,age){
    Father.call(this,name)
    this.age=age
}
var father=new Father()
Son.prototype=father
father.constructor=Son
//让父类的实例成为子类的原型对象
//把子类原型对象中的constructor属性指回子类构造函数

这样当子类调用父类中的方法时,先在自己的实例中寻找,找不到去原型对象中寻找(父类的那一个实例),找不到就去父类的原型对象中寻找 这样就实现了对父类原型对象的继承