面向对象的程序设计——实现继承
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版)》相关文章推荐
- Python--面向对象的程序设计之继承实现的原理(继承顺序)、封装、property
- day32--面向对象的程序设计之继承实现的原理(继承顺序)、封装、property
- JavaScript 面向对象程序设计(下)——继承与多态
- JavaScript 面向对象程序设计(下)——继承与多态
- 面向对象程序设计——继承
- 面向对象的程序设计(九)寄生组合式继承
- JavaSE 拾遗(5)——JavaSE 面向对象程序设计语言基础(5)...继承和多态
- JavaScript 面向对象程序设计(下)——继承与多态
- JavaScript 面向对象程序设计(下)——继承与多态
- JS Pro - 面向对象的程序设计 - 继承
- Javascript乱弹设计模式系列(0) - 面向对象基础以及接口和继承类的实现
- 面向对象的程序设计(八)寄生式继承
- 面向对象程序设计:继承成员访问控制机制
- JavaScript 面向对象程序设计(下)——继承与多态
- 利用prototype属性自定义对象,实现对象继承等面向对象设计
- JavaScript 面向对象程序设计(下)——继承与多态
- JavaScript 面向对象程序设计(下)——继承与多态
- 《面向对象程序设计与VC++实现》--第一章 疑难点汇集
- 面向对象的程序设计(六)组合继承
- 面向对象的程序设计-14-用虚函数实现价格的统计(实例)