根据少一点套路,多一点真诚这个原则,继续学习。

借用构造函数继承

在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数
(constructor stealing)的技术(有时候也叫做伪造对象或经典继承)。这种技术的基本思想相当简单,即
在子类型构造函数的内部调用超类型构造函数。

基本模式

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

基本思想

借用构造函数的基本思想就是利用call或者apply把父类中通过this指定的属性和方法复制(借用)到子类创建的实例中。因为this对象是在运行时基于函数的执行环境绑定的。也就是说,在全局中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。call 、apply方法可以用来代替另一个对象调用一个方法。call、apply 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。   

所以,这个借用构造函数就是,new对象的时候(注意,new操作符与直接调用是不同的,以函数的方式直接调用的时候,this指向window,new创建的时候,this指向创建的这个实例),创建了一个新的实例对象,并且执行SubType里面的代码,而SubType里面用call调用了SuperTyep,也就是说把this指向改成了指向新的实例,所以就会把SuperType里面的this相关属性和方法赋值到新的实例上,而不是赋值到SupType上面。所有实例中就拥有了父类定义的这些this的属性和方法。

优势

相对于原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向超类型构造函数传递参数。因为属性是绑定到this上面的,所以调用的时候才赋到相应的实例中,各个实例的值就不会互相影响了。

例如:

function SuperType(name){
this.name = name;
}
function SubType(){
//继承了SuperType,同时还传递了参数
SuperType.call(this, "Nicholas");
//实例属性
this.age = 29;
}
var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //

劣势

如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

组合继承

组合继承(combination inheritance),有时候也叫做伪经典继承。是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。

基本思想

思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。

基本模型

function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(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(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27

优势

组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为JavaScript 中最常用的继承模式。

劣势

组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。虽然子类型最终会包含超类型对象的全部实例属性,但我们不得不在调用子类型构造函数时重写这些属性。

  

To be continued...

最新文章

  1. mysql表名查询sql
  2. MyBatis代码自动生成(利用命令)
  3. Codeforces Round #249 (Div. 2) A - Queue on Bus Stop
  4. hdu 1061 快速幂
  5. 《c程序设计语言》读书笔记--闰年和字符输入不用 && ||
  6. 一步步学Mybatis-实现简单的分页效果逻辑 (5)
  7. ●linux进程的查看与操作●
  8. C语言 rand()函数的用法
  9. svn设置
  10. 扯谈spring mvc之WebApplicationContext的继承关系
  11. (一)CodeMirror - 基本应用
  12. PHP数组关于数字键名的问题
  13. 【17-06-19】Java进阶自测:面向对象基础知识掌握了吗?(附答案及个人解析)
  14. 提高SQL查询效率
  15. python - Random常用方法记录
  16. PHP实现类似题库抽题效果
  17. MySQL 深入浅出数据库索引原理(转)
  18. flask内容学习第三天(flak中的csrf跨站请求)
  19. mac下nginx搭建
  20. ARC062 - F. Painting Graphs with AtCoDeer (Polya+点双联通分量)

热门文章

  1. Shell特殊变量
  2. Android Ormlite 学习笔记2 -- 主外键关系
  3. 代码的坏味道(17)——夸夸其谈未来性(Speculative Generality)
  4. background例子
  5. webpack学习总结
  6. Android开发学习——动画
  7. Java 进阶 hello world! - 中级程序员之路
  8. 浅谈单片机中C语言与汇编语言的转换
  9. 【每日一linux命令1】linux命令路径
  10. 介绍一位OWin服务器新成员TinyFox