function Animal(){
}
Animal.prototype = {
group : '',
gender : '',
eat : function(){
return 'Yum , food! nom nom';
},
sleep : function(){
return 'zzzzzz...';
}
}
function Bird(){
}
function extend(subClass,superClass){
/*声明一个空构造函数*/
function fn(){}
/*将空函数原型指向父类,这样fn就有了superClass成员了,fn是为下面子类继承做准备用的。*/
fn.prototype = superClass.prototype;
/*将子类的原型指向空函数的实例*/
subClass.prototype = new fn();
/*因为前面改变了子类构造函数的原型会影响constructor属性(指向Object了),所以重新指定一下子类的constructor属性*/
subClass.prototype.constructor = subClass;
/*添加一个属性,保存子类的父类构造函数*/
subClass.baseConstructor = superClass;
/*添加一个属性,保存子类的父类构造函数原型*/
subClass.__super__ = superClass.prototype;
}
extend(Bird , Animal);
var bird = new Bird();
console.log(bird.eat());今天在书上看到这段代码,自己动手试了下,运行成功后,感觉这代码有点眼熟,然后打开Extjs的ext-all-debug.js源码,找到extend方法。果然神似,曾经看的头晕的代码,今天终于明白了,发帖来跟大家分享下,加了点注释,不对的地方希望大家拍砖指正,谢谢。
我来个:
function Animal(){
}
Animal.prototype = {
group : '',
gender : '',
eat : function(){
return 'Yum , food! nom nom';
},
sleep : function(){
return 'zzzzzz...';
},
walk : {
"method" : "walk"
}
}
function Bird(){
}
function Person(){
}
function extend(subClass,superClass){
/*声明一个空构造函数*/
function fn(){}
/*将空函数原型指向父类,这样fn就有了superClass成员了,fn是为下面子类继承做准备用的。*/
fn.prototype = superClass.prototype;
/*将子类的原型指向空函数的实例*/
subClass.prototype = new fn();
/*因为前面改变了子类构造函数的原型会影响constructor属性(指向Object了),所以重新指定一下子类的constructor属性*/
subClass.prototype.constructor = subClass;
/*添加一个属性,保存子类的父类构造函数*/
subClass.baseConstructor = superClass;
/*添加一个属性,保存子类的父类构造函数原型*/
subClass.__super__ = superClass.prototype;
}
extend(Bird , Animal);
extend(Person , Animal);
var bird = new Bird();
var person = new Person(); bird.walk.method = "fly";
console.log(person.walk.method);结果是神马呢?不错就是 fly,在使用new 操作符后,内部对象并没有新建拷贝..真令人沮丧...
要小心这种情况带来的程序出错,也算是空函数继承的一个小小bug吧。
/*将子类的原型指向空函数的实例*/
subClass.prototype = new fn();为什么要new fn(),直接fn.prototype 不行吗?new fn()是直接继承自fn.prototype
function extend(subClass,superClass){
if(Object.create){
subClass.prototype=Object.create(superClass.prototype,{});
}
else{
function fn(){}
fn.prototype = superClass.prototype;
subClass.prototype = new fn();
}
subClass.prototype.constructor = subClass;
subClass.baseConstructor = superClass;
subClass.__super__ = superClass.prototype;
}
extend : function(){
// inline overrides
var io = function(o){
for(var m in o){
this[m] = o[m];
}
};
var oc = Object.prototype.constructor; return function(sb, sp, overrides){
if(typeof sp == 'object'){
overrides = sp;
sp = sb;
sb = overrides.constructor != oc ? overrides.constructor : function(){
sp.apply(this, arguments);
};
}
var F = function(){},
sbp,
spp = sp.prototype; F.prototype = spp;
sbp = sb.prototype = new F();
sbp.constructor=sb;
sb.superclass=spp;
if(spp.constructor == oc){
spp.constructor=sp;
}
sb.override = function(o){
Ext.override(sb, o);
};
sbp.superclass = sbp.supr = (function(){
return spp;
});
sbp.override = io;
Ext.override(sb, overrides);
sb.extend = function(o){
return Ext.extend(sb, o);
};
return sb;
};
}()这是100%的extjs 3.3.1的扩展函数,你看看有什么区别!
所以一般用组合继承,prototype加apply或call。把方法写在原型上,属性写在构造函数里面。
如下:function Animal(group,gender,walk){
this.group = group;
this.gender = gender;
this.walk = walk;
}
Animal.prototype = {
eat : function(){
return 'Yum , food! nom nom';
},
sleep : function(){
return 'zzzzzz...';
}
}
function Bird(group,gender,walk){
Animal.call(this,group,gender,walk);
}
function Person(group,gender,walk){
Animal.call(this,group,gender,walk);
}
function extend(subClass,superClass){
/*声明一个空构造函数*/
function fn(){}
/*将空函数原型指向父类,这样fn就有了superClass成员了,fn是为下面子类继承做准备用的。*/
fn.prototype = superClass.prototype;
/*将子类的原型指向空函数的实例*/
subClass.prototype = new fn();
/*因为前面改变了子类构造函数的原型会影响constructor属性(指向Object了),所以重新指定一下子类的constructor属性*/
subClass.prototype.constructor = subClass;
/*添加一个属性,保存子类的父类构造函数*/
subClass.baseConstructor = superClass;
/*添加一个属性,保存子类的父类构造函数原型*/
subClass.__super__ = superClass.prototype;
}
extend(Bird , Animal);
extend(Person , Animal);
var bird = new Bird('aa','bb',{method:'walk'});
var person = new Person('cc','dd',{method:'xxx'});
bird.walk.method = "fly";
console.log(person.walk.method);
我说像的是继承的那几段代码,Extjs的extend方法还给子类添加静态方法:override,实例方法:override,extend。还有其它一些。