js 设计模式 第四章
2012-10-17 09:02
323 查看
继承
why?
多个类公用的功能,如果重复拷贝,一方面,工作量大,另一方面,如果公用功能需要修改,则需要修改所有类中的这个功能,重复工作量大。
为了减少复制以及带来的不利于修改的问题,我们需要继承
how?
三种方法:Classical Inheritance Prototypal Inheritance Mixin Classes
what?
第一种方法:Classical Inheritance
利用原型链,实现继承
这种方法的实现步骤是:
1 在构造函数中,调用父类的构造函数,通过apply或者call方法,将父类的执行环境变成子类的执行环境。这可以让子类有父类的public 属性
2 建立原型链。在js中,所有对象都有一个prototype的属性,这个属性指向别的对象或者null。当访问对象的一个属性时,寻找的路径方式是:先在对象内寻找,如果不存在,则到这个对象的prototype指向的对象中找,还是没有找到,则到prototype指向对象的prototype指向对象中继续寻找,知道找到属性或者prototype为null。利用js的这个特性,要让子类继承父类,只需要让子类的prototype 指向父类的一个实例。
3 将子类的prototype对象的constructor属性赋值为子类对象名。因为当你将子类的prototype属性赋值为父类的一个实例时,子类的prototype被清空了。
为了简化继承的过程,我们通过函数,封装上面的流程
在extend 方法中,有两个地方需要再解释下:
1 在继承中,为了获得父类的原型链,我们让子类的prototype指向了父类的一个实例对象,而父类实例化对象的属性并不是我们需要的,如果父类构造函数比较负责,这样就照成了不小的浪费。在extend 中,我们通过一个空的类,让空类的prototype指向了父类的原型链,进而让子类的原型链执行空类的对象,达到了目的。
2 如果父类的prototype被重置,而没有重新给constructor 赋值,constructor 属性将指向Object,故通过判断,如果没有赋值,则重新给他赋值。这样,就能保证在注释3的位置中,superclass.constructor ,指向了正确的类。
第一种方法:Prototypal Inheritance
这种方法,通过常量对象来模拟继承。这种方法的好处,是所有子类默认公用父类的属性和方法,是一种节约内存的有效方法。而经典的继承方式中,所有子类对象都保存了一份属性。
第三种方法:Mixin Classes
通过将公用类的prototype中的方法,拷贝到类中,实现对类能力的增强
关键的函数
Mixin 中通过prototype 包含公用的函数
augment 中,将Mixin中的函数都拷贝到receivingClass中,除非receivingClass中已定义该方法。
几种方法的比较:
classical inheritance 简单易懂,最接近其他语言继承的流程
prototypal inheritance 适用与内存比较紧张的情况
mixin Classes 适合增强类,两个类在语义世界里,没有继承关系
why?
多个类公用的功能,如果重复拷贝,一方面,工作量大,另一方面,如果公用功能需要修改,则需要修改所有类中的这个功能,重复工作量大。
为了减少复制以及带来的不利于修改的问题,我们需要继承
how?
三种方法:Classical Inheritance Prototypal Inheritance Mixin Classes
what?
第一种方法:Classical Inheritance
function Animal(type){ this.type = type; } Animal.prototype.getType = function(){ return this.type; }
利用原型链,实现继承
function Pat(type,name){ Animal.call(this,type); this.name = name; } Pat.prototype = new Animal(); Pat.prototype.constructor = Pat; Pat.prototype.getName = function(){ return this.name; }
这种方法的实现步骤是:
1 在构造函数中,调用父类的构造函数,通过apply或者call方法,将父类的执行环境变成子类的执行环境。这可以让子类有父类的public 属性
2 建立原型链。在js中,所有对象都有一个prototype的属性,这个属性指向别的对象或者null。当访问对象的一个属性时,寻找的路径方式是:先在对象内寻找,如果不存在,则到这个对象的prototype指向的对象中找,还是没有找到,则到prototype指向对象的prototype指向对象中继续寻找,知道找到属性或者prototype为null。利用js的这个特性,要让子类继承父类,只需要让子类的prototype 指向父类的一个实例。
3 将子类的prototype对象的constructor属性赋值为子类对象名。因为当你将子类的prototype属性赋值为父类的一个实例时,子类的prototype被清空了。
为了简化继承的过程,我们通过函数,封装上面的流程
function extend(subClass,superClass){ var F = function(){}; //1 F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; //让子类有一个类属性,指向父类 subClass.superclass = superClass.prototype; if(superClass.prototype.constructor == Object.prototype.constructor){//2 superClass.prototype.constructor = superClass; } }利用extend 继承的方法如下:
function Pat(type,name){ Pat.superclass.constructor.call(this,type);//3 this.name = name; } extend(Pat,Animal); Pat.prototype.getName = function(){ return this.name; }
在extend 方法中,有两个地方需要再解释下:
1 在继承中,为了获得父类的原型链,我们让子类的prototype指向了父类的一个实例对象,而父类实例化对象的属性并不是我们需要的,如果父类构造函数比较负责,这样就照成了不小的浪费。在extend 中,我们通过一个空的类,让空类的prototype指向了父类的原型链,进而让子类的原型链执行空类的对象,达到了目的。
2 如果父类的prototype被重置,而没有重新给constructor 赋值,constructor 属性将指向Object,故通过判断,如果没有赋值,则重新给他赋值。这样,就能保证在注释3的位置中,superclass.constructor ,指向了正确的类。
第一种方法:Prototypal Inheritance
fuction clone(object){ function F(){} F.prototype = object; return new F; }
var Animal = { type : "dog", getType:function(){ return this.type; } } var Pat = clone(Animal); Pat.name ="xiaoge"; Pat.getName = function(){ return this.name; } var cat = clone(Pat); cat.name="mimi"; alert(cat.getName);//mimi
这种方法,通过常量对象来模拟继承。这种方法的好处,是所有子类默认公用父类的属性和方法,是一种节约内存的有效方法。而经典的继承方式中,所有子类对象都保存了一份属性。
第三种方法:Mixin Classes
通过将公用类的prototype中的方法,拷贝到类中,实现对类能力的增强
关键的函数
var Mixin = function(){}; Mixin.portotype = { serialize:function(){ var output = []; for(key in this){ output.push(key+':' + this[key]); return output.join(','); } } }; function augment(receivingClass,givingClass){ for(methodName in givingClass.prototype){ if(!receivingClass.prototype[methodName){ receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } }
Mixin 中通过prototype 包含公用的函数
augment 中,将Mixin中的函数都拷贝到receivingClass中,除非receivingClass中已定义该方法。
几种方法的比较:
classical inheritance 简单易懂,最接近其他语言继承的流程
prototypal inheritance 适用与内存比较紧张的情况
mixin Classes 适合增强类,两个类在语义世界里,没有继承关系
相关文章推荐
- JS设计模式之装饰者模式
- JS设计模式之状态模式
- js原生设计模式——3简单工厂模式\js面向对象编程实例
- js设计模式--迭代器模式
- JS设计模式之享元模式
- JS常用的设计模式(8)——访问者模式
- js原生设计模式——8单例模式
- 大熊君说说JS与设计模式之------代理模式Proxy
- 【JS设计模式】工厂方法模式
- JS设计模式之工厂模式
- 【js设计模式笔记---封装】
- 由表单提交引伸的对JS设计模式的思考
- 【js设计模式笔记---方法的链式调用】
- JS-12种设计模式
- js设计模式(1)
- JS设计模式——7.工厂模式(示例-XHR)
- js设计模式之建造者模式
- js设计模式小结
- node.js笔记之订阅发布设计模式
- JS设计模式一:单例模式