title: JS对象(3)典范对象建立与继续情势
date: 2016-09-28
tags: JavaScript
0x01 组合情势建立对象
JS 中建立一个对象的体式格局多种多样,每种体式格局都有本身瑕玷或许长处,详细的能够参考____
而组合运用组织函数情势和原型情势来建立自定义范例算是最常见的体式格局了。
在组合情势中,组织函数用于定义实例属性,而原型用于定义要领和同享的属性。
云云,每一个实例都邑有本身的一份实例属性的副本,又同享着对要领的援用。
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["jack", "marli"]
}
Person.prototype = {
// 运用字面量情势重写原型
constructor : Person,
sayName : function(){
console.log(this.name);
}
}
var person1 = new Person("刘德华",54,"歌手 演员")
person1.friends.push("成龙")
var person2 = new Person("特朗普",60,"企业家 纨绔子弟 总统")
console.log(person1.sayName()+"的朋侪: "+person1.friends)
//刘德华的朋侪: jack,marli,成龙
console.log(person2.name+"的朋侪: " +person2.friends)
//特朗普的朋侪: jack,marli
当修正了 person1.friends
并不会影响到 person2.friends
,由于它们离别援用了差别的数组。
如今,对 Person 的原型举行以下修正:
Person.prototype = {
// 运用字面量情势重写原型
constructor : Person,
sex:'man',
hobby:['woman','money','food'],
sayName : function(){
console.log(this.name);
}
}
如上,我们新增加了 sex
和 hobby
两个同享属性。
person1.sex = "woman"
console.log(person1.sex)
// woman
console.log(person2.sex)
// man
person1.hobby.push("reputation")
// ["woman", "money", "food", "reputation"]
console.log(person2.hobby)
// ["woman", "money", "food", "reputation"]
我们尝试在 person1
中将 Person
原型里的 sex
修正为 woman
,person2
并没有受到影响,纵然 sex
属性是属于 Person
原型中的同享属性。这很轻易明白,由于 Person
中的 sex
是字符串,即属于六种原始范例中的一种。
然则,当我门对 person1
中的 hobby
推入一个元素的时刻,person2
中 hobby
一样被更改了。这也很轻易明白,hobby
数数组,是援用范例的,且存在于 Person
的原型中,即它是同享属性,那末在任何实例中的操纵都邑影响到原型中的同享属性。
0x02 组合式继续
作为典范继续情势,组合式继续情势算是 JS 中运用最多的了。
其头脑是运用原型链完成对原型属性和要领的继续,而经由过程借用组织函数来完成对实例属性的继续。
function SuperType(name){
this.name = name;
this.colors = ["red","blue","pink"];
}
SuperType.prototype = {
// 重写原型
constructor: SuperType,
// 将原型的组织函数指向 SuperType
job:["teacher","student"],
sayName:function(){
console.log(this.name)
}
}
function SubType(name, age){
SuperType.call(this, name); // **第二次挪用 SuperType 组织函数**
// 继续父类的实例属性,也因此而覆蓋了原型继续中的同名属性
this.age = age;
}
SubType.prototype = new SuperType(); // **第一次挪用 Supertype 组织函数**
// 此时 SubType 的原型中将会包含 SuperType 的一切属性和要领(包含实例属性,同享属性,以及同享要领)
SubType.constructor = SubType;
SubType.prototype.sayAge = function(){
// 继续而来的原型不能经由过程对象字面量的体式格局被重写,等于增加了 constructor 属性也没用
console.log(this.age)
}
var aSubType = new SubType("jack", 24)
aSubType.sayName()
// jack
var aSuperType = new SuperType("mack",35)
aSubType.job.push("softfore engineering")
console.log(aSuperType.job)
// ["teacher", "student", "softfore engineering"]
console.log(aSubType.job)
// ["teacher", "student", "softfore engineering"]
以下,我们也许了解了组合式继续,但,正如星号(**)所标记的那样,组合继续存在一个不足的处所,就是不管在何种情况下,都邑挪用两次超范例构函数。一次是在建立子范例原型的时刻,一次是在子范例组织函数内部。
怎样想处理这个题目,能够进一步的运用寄生组合式继续情势,它被认为是援用范例最理想的继续范式,也是完成基于范例继续的最有用体式格局。
0x03 寄生组合式继续
运用寄生组合式继续能够没必要为了指定子范例的原型而挪用超范例的组织函数,我们所须要的无非是超范例的一个副本罢了。
以下是寄生组合式继续的基本情势:
function inheritPrototype(subType, superType){
var prototype = Object(superType.prototype)
// 建立对象
prototype.constructor = subType;
// 加强对象
subType.prototype = prototype;
// 指定对象
}
inheritPrototype() 函数接收两个参数:子范例组织函数和超范例组织函数。在函数中我们起首建立了一个超范例原型的一个副本,然后为建立的副本增加 constructor
属性,从而填补因重写原型而落空的默许的 constructor 属性,末了我们将新建立的对象(原型副本)赋给子范例的原型。
云云,便能够运用 inheritPrototype() 函数替代组合式继续情势中为子类原型赋值的操纵了
function SuperType(name){
this.name = name;
this.colors = ["red","blue","pink"];
}
SuperType.prototype = {
// 重写原型
constructor: SuperType,
// 将原型的组织函数指向 SuperType
job:["teacher","student"],
sayName:function(){
console.log(this.name)
}
}
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
function inheritPrototype(subType, superType){
var prototype = Object(superType.prototype) // 拷贝父级对象原型
prototype.constructor = subType; //将子类原型组织属性指向其子类组织函数
subType.prototype = prototype; // 指定对象
}
inheritPrototype(SubType, SuperType);
var aSubType = new SubType("jack", 24)
aSubType.sayName()
// jack
console.log(aSubType.colors)
//["red", "blue", "pink"]