您的位置:首页 > 其它

面向对象的程序设计——实现继承

2017-05-19 11:23 609 查看

借用构造函数

原理

在子类型构造函数的内部调用超类型构造函数

例如

function SuperType() {
this.colors=["red","blue","white"];
}
function SubType() {
//继承了SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
var instance2= new SubType();
console.log(instance1.colors);
console.log(instance2.colors);


结果



优点

可以在子类型构造函数中向超类型构造函数传递参数

例如

function SuperType(name) {
this.name = name;
}
function SubType() {
//继承了SuperType
SuperType.call(this,"Mike");
this.age = 20;
}
var instance = new SubType();
console.log(instance.name);
console.log(instance.age);


结果



问题

1.方法在构造函数中定义,函数无法复用

2.在超类型定义的原型中定义的方法,对于子类型是不可见的,结果所有类型只能使用构造函数模式

组合继承

原理

将原型链和借用构造函数组合一起,使用原型链实现对原型链实现对原型属性和方法的继承,通过借用构造函数实现对实例属性的继承

优点

1.避免了原型链和借用构造函数的缺陷,融合了它们的优点,是JavaScript中最常见的继承模式

2.instanceof和isPrototypeOf()可以识别基于组合继承创建的对象

例如

function SuperType(name) {
this.name = name;
this.colors=["red","blue","yellow"];
}
SuperType.prototype.sayName = function () {
console.log(this.name);
};
function SubType(name,age) {
SuperType.call(this,name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function () {
console.log(this.age);
};
var instance1 = new SubType("Mike",21);
instance1.colors.push("black");
console.log(instance1.colors);
instance1.sayName();
instance1.sayAge();

var instance2= new SubType("Greg",29);
console.log(instance2.colors);
instance2.sayName();
instance2.sayAge();


结果



分析

(1)SubType构造函数在调用SuperType构造函数时传入name参数,又定义了自己的属性age

(2)SuperType的实例赋值给了SubType的原型,又在新原型上定义了方法sayAge()。

(3)两个不同的SubType实例分别有自己的属性,又可以使用相同的方法

问题

会调用两次超类型构造函数,一次是在创建子类型原型的时候,另一次是在子类型构造函数内部

例如

SuperType.call(this,name);//第二次调用SuperType()
...
SubType.prototype = new SuperType();//第一次调用SuperType()


原型式继承

原理

借助原型基于已有的对象创建新对象,同时不必因此创建自定义类型

例如

function object(o) {
function F() {}
F.prototype = o;
return new F();
}


从本质上看,object()对传入其中的对象执行了一次浅复制

例如

 function object(o) {
function F() {}
F.prototype = o;
return new F();
}

var person = {
name:"Mike",
friends:["john","xiao","ha"]
};
var aPerson = object(person);
aPerson.name = "Greg";
aPerson.friends.push("Bob");

var yPerson = object(person);
yPerson.name = "Linda";
yPerson.friends.push("Barbie");

console.log(person.friends);


结果



规范化原型继承

ECMAScript5通过Object.create()方法规范了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选)一个为新对象定义额外属性的对象。

例如:传入一个参数

var person = {
name:"Mike",
friends:["john","xiao","ha"]
};
var aPerson = Object.create(person);
aPerson.name = "Greg";
aPerson.friends.push("Bob");

var yPerson =  Object.create(person);
yPerson.name = "Linda";
yPerson.friends.push("Barbie");

console.log(person.friends);


结果



例如:传入第二个参数,即属性的描述符

var person = {
name:"Mike",
friends:["john","xiao","ha"]
};
var aPerson = Object.create(person,{
name:{
value:"Greg"
}
});
console.log(aPerson.name);


结果



优点

如果只想让一个对象与另一个对象保持类似的情况,可以用原型式继承

问题

引用类型值的属性始终共享

寄生式继承

原理

创建一个仅用于封装继承过程的函数,在内部以某种方式增强对象,最后再返回对象

例如

function createAnother(original) {
var clone = Object.create(original);
clone.sayHi = function () {
console.log("Hi");
};
return clone;
}

var person = {
name:"Mike",
friends:["Shelby","Court","Van"]
};
var aPerson = createAnother(person);
aPerson.sayHi();


结果、



问题

不能做到函数复用而降低效率

寄生组合式继承

原理

通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

例如

function inheritPrototype(subType,superType) {
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}


优点

不必为了指定子类型的原型而调用超类型的构造函数

例如

 function inheritPrototype(subType,superType) {
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name) {
this.name = name;
this.colors=["red","blue","black"];

}
SuperType.prototype.sayName = function () {
console.log(this.name);
};
function SubType(name,age) {
SuperType.call(this,name);
this.age = age;

}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function () {
console.log(this.age);
}


分析:

(1)高效率体现在它只调用了一次SuperType构造函数,避免在SubType.prototype上面创建不必要的、多余的属性。

(2)原型链保持不变

(3)正常使用instanceof和isPrototypeOf()

总结

(1)原型式继承:可以不必预定义构造函数的情况下实现继承,其本质是执行对给定对象的浅复制

(2)寄生式继承:基于某个对象或者某些信息创建一个对象,然后增强对象,最后返回对象

(3)寄生组合式继承:集寄生式继承和组合继承的优点于一身,是引用类型最理想的继承方式

参考

《JavaScript高级程序设计(第3版)》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: