创建对象模式、继承、类和面向对象的整理总结
对象的创建方式除了常用的{}方式,还有一些其他的方式,其他的创建方式也都有各自的优缺点,但是组合不同种类的对象创建模式可以快速创建需要的对象,同时还能实现对象的继承;类其实就是一个快速创建对象的简便模板,本事上还是一种语法糖;
创建对象模式的整理总结
1.工厂模式:
封装一个函数,在函数内部创建一个对象,然后return返回这个对象;但是这种模式不能检测出来对象的构造函数的类型;
2.构造函数模式:
封装一个函数,在函数内部通过this.atrr=atrr来给新创建的对象接收传进来的参数;然后通过new Consttuct(arg1,arg2,...)来创建一个新对象,这种方式可以检测出来对象的构造函数的类型,但是新对象属性值如果是函数的话,则会重复创建函数,会有相同功能函数不能复用、浪费内存的缺点;这个问题可以通过把对象的方法函数放到函数外部,只需要定义声明一次函数;但是这又导致了代码的散乱的问题;
3.原型模式:
创建一个空的构造函数,然后在构造函数的prototype上添加属性,属性值可以是引用类型和非引用类型,并且属性可以在所有实例上共享,这样就不用重复创建函数且代码也不显得散乱;但是如果属性值是数组或者对象,并在某一实例上进行修改时,则会导致其变动会在所有实例上实时共享的问题;注意:创建实例后在原型对象上添加属性方法后,是可以访问整个原型对象的,包括添加的原型方法;但是创建实例后,如果重写原型对象(用另一个对象覆盖了原型对象),就不可以再访问原型对象了;因为后者是切断了原来的原型对象引用指针,前者并没有切断原型对象的引用指针,只是改变了原型对象的内容。
继承
1.原型链继承:
父子构造函数都用采用构造函数模式来给实例添加实例属性,然后通过给构造函数的prototype添加方法,实现每个实例都有独自的实例属性同时各个实例又能共享方法;然后把父构造函数创建的实例赋值给子构造函数函数的prototype,实现子构造函数继承父实例的特性的要求,然后再把子实例赋值给孙子构造函数的prototype,如此循环往复就是原型链继承,最终实现一个实例可以继承多个构造函数的特性的要求;
缺点:和原型模式一样会有引用类型的属性值变动在各个实例间实时共享的缺点;子类型在实例化时不能给父类型的构造函数传参。事实上,我们无法在不影响所有对象实例的情况下把参数传进父类的构造函数。
2.盗用构造函数继承:
创建一个子构造函数,然后在子构造函数中调用父构造函数,并将父构造函数的this指向子实例,这样在子类型实例化时就可以将父类的实例属性添加到子类实例上,从而实现子类继承父类的目的;
优点:每一个子类实例都有从父类继承来的独有实例属性,并且子类也可以向父类传递参数;
缺点:在构造函数中定义的方法函数不能复用;子类不能访问父类构造函数的原型;
3.组合继承:
将原型链继承和构造函数继承一起使用,结合两者的优点--通过原型链继承实现访问父类上的属性方法、避免构造函数内部重复定义方法函数,通过构造函数继承父类的实例属性。
优点:每个子类实例都可以拥有独有的实例属性--父类继承和子类自有;避免方法函数重复定义;可以访问父类原型属性;可以通过子类向父类传递参数;而且组合继承也保留了 instanceof 操作符和 isPrototypeOf()方法识别合成对象的能力。
缺点:父类构造函数调用了两次,相同属性添加了两次,实例属性覆盖了原型属性,效率降低;
4.原型式继承
5.寄生式继承
6.寄生式组合继承
为了解决组合继承调用两次父类构造函数,所以用寄生式组合继承只需要调用一次父类构造函数,提高了效率;
function inheritPrototype(subType, superType) {
类class
Class className{
construct(arg){ //创建对象时的构造函数
this.arg=arg; //this指向对象实例,给对象实例添加自有属性
}
sayname(){ //添加到类原型上,this指向谁呢?在各个实例间共享
console.log(this.arg)
}
staic sayname(){ // 绑定在类上,只能通过类本身调用,不能通过实例调用
console.log(this.arg) //this指向类本身
}
}
Class chirldClassName extend className {
//子类的代码区域
construct(arg){ //创建对象时的构造函数
super() //代指构造函数,在调用super()前不能引用this;
this.arg=arg; //this指向对象实例,给对象实例添加自有属性
}
staic sayname(){ // 绑定在类上,只能通过类本身调用,不能通过实例调用
super.sayname(); //通过 super 调用继承的类上定义的静态方法
console.log(this.arg) //this指向类本身
}
}