批判我的原型继承模式
Critique my prototypal inheritance pattern
我决定使用 Object.create,因为它看起来比使用 'new' 并且必须为每个函数编写 Car.prototype.func1 = function(){} 更直观, 例如;好像有点太干了。
我顿悟了使用 $.extend 来扩充属性和函数,这使得从我想使用的任何对象中获取代码变得更加容易。一旦对象被扩展,我就使用 Object.create() 来设置原型,所以这些函数对所有实例都是通用的,并将属性作为第二个参数传递。
下面的模式可以吗? jsfiddle
// props use Object.defineProperties() format; can configure each prop as writable, enumerable, etc
var Vehicle = {
props : { 'colour' : {value:'black'}, 'wheels' : {value:4} },
proto : { 'drive' : function(){console.log('drive ' + this.colour + ' ' + this.wheels);} }
};
var Ferrari = {
props : { 'colour' : {value:'red'}, 'seats' : {value:2} },
proto : { 'fast' : function(){console.log('ferrari power ' + this.colour + ' ' + this.wheels + ' ' + this.seats);} }
};
function init(){
// copy Vehicle object, so it remains untouched
var vehicle = $.extend(true,{}, Vehicle);
// augment vehicle super-class with sub-class
$.extend(vehicle.props, Ferrari.props);
$.extend(vehicle.proto, Ferrari.proto);
// prototypal inheritance
var ferrari = Object.create(vehicle.proto, vehicle.props);
ferrari.drive();
ferrari.fast();
}
init();
编辑:我放弃了这个想法,太乱了;我正在使用原型模式,显示在 this article.
的末尾
这是创造性的代码,但感觉很混乱,并且引入了太多附带的复杂性,例如需要 jQuery(如果您的项目已经依赖于 jQuery,这未必是件坏事). JavaScript具体是基于原型继承设计的...为什么不利用它呢?
此外,关于您对添加原型属性似乎过于重复的感觉:
var Cat = function() { ... };
// then when defining the prototype...
Cat.prototype.purr = function() { ... };
Cat.prototype.meow = function() { ... };
您会发现出于多种原因(相对于我将在下面展示的方法),人们通常推荐使用上述定义原型属性的方法,原因之一是关于垃圾收集和消除循环引用。但是,如果您担心 "repeating yourself" 太多,只需将原型设置为普通对象即可:
Cat.prototype = {
purr: purr,
meow: meow
};
function purr() {
// whatever
}
function meow() {
// whatever
}
第二种方法,如上所示,利用了JavaScript的函数提升并引入了类似于the revealing module pattern的概念。
您不应该使用 $.extend
进行继承,您应该在 class 的定义中立即声明继承,而不是稍后在 init
函数中声明继承。
另外,您的“增强型车辆超级-class 与子class”似乎真的很倒退。需要“复制 Vehicle 对象,因此它保持不变”并且您正在从 vehicle
而不是从 [= 创建 ferrari
实例来强调这一点16=].
我建议使用两个辅助函数:
function inherit(superClass, props, proto) {
return {
props: $.extend(Object.create(superClass.props), props),
proto: $.extend(Object.create(superClass.proto), proto)
};
}
function create(template) {
return Object.create(template.proto, template.props);
}
你可以像这样使用
var Vehicle = {
props : { 'colour' : {value:'black'}, 'wheels' : {value:4} },
proto : { 'drive' : function(){console.log('drive ' + this.colour + ' ' + this.wheels);} }
};
var Ferrari = inherit(Vehicle, {
'colour' : {value:'red'},
'seats' : {value:2}
}, {
'fast' : function(){console.log('ferrari power ' + this.colour + ' ' + this.wheels + ' ' + this.seats);}
});
var ferrari = create(Ferrari);
ferrari.drive();
ferrari.fast();
除了这些问题,你的模式还不错。使用纯原型继承是一种既定的模式。您可以通过向模板对象 (classes) 添加初始化函数来修改它,例如命名为.constructor
,您又回到了典型 class 模式的力量。
我决定使用 Object.create,因为它看起来比使用 'new' 并且必须为每个函数编写 Car.prototype.func1 = function(){} 更直观, 例如;好像有点太干了。
我顿悟了使用 $.extend 来扩充属性和函数,这使得从我想使用的任何对象中获取代码变得更加容易。一旦对象被扩展,我就使用 Object.create() 来设置原型,所以这些函数对所有实例都是通用的,并将属性作为第二个参数传递。
下面的模式可以吗? jsfiddle
// props use Object.defineProperties() format; can configure each prop as writable, enumerable, etc
var Vehicle = {
props : { 'colour' : {value:'black'}, 'wheels' : {value:4} },
proto : { 'drive' : function(){console.log('drive ' + this.colour + ' ' + this.wheels);} }
};
var Ferrari = {
props : { 'colour' : {value:'red'}, 'seats' : {value:2} },
proto : { 'fast' : function(){console.log('ferrari power ' + this.colour + ' ' + this.wheels + ' ' + this.seats);} }
};
function init(){
// copy Vehicle object, so it remains untouched
var vehicle = $.extend(true,{}, Vehicle);
// augment vehicle super-class with sub-class
$.extend(vehicle.props, Ferrari.props);
$.extend(vehicle.proto, Ferrari.proto);
// prototypal inheritance
var ferrari = Object.create(vehicle.proto, vehicle.props);
ferrari.drive();
ferrari.fast();
}
init();
编辑:我放弃了这个想法,太乱了;我正在使用原型模式,显示在 this article.
的末尾这是创造性的代码,但感觉很混乱,并且引入了太多附带的复杂性,例如需要 jQuery(如果您的项目已经依赖于 jQuery,这未必是件坏事). JavaScript具体是基于原型继承设计的...为什么不利用它呢?
此外,关于您对添加原型属性似乎过于重复的感觉:
var Cat = function() { ... };
// then when defining the prototype...
Cat.prototype.purr = function() { ... };
Cat.prototype.meow = function() { ... };
您会发现出于多种原因(相对于我将在下面展示的方法),人们通常推荐使用上述定义原型属性的方法,原因之一是关于垃圾收集和消除循环引用。但是,如果您担心 "repeating yourself" 太多,只需将原型设置为普通对象即可:
Cat.prototype = {
purr: purr,
meow: meow
};
function purr() {
// whatever
}
function meow() {
// whatever
}
第二种方法,如上所示,利用了JavaScript的函数提升并引入了类似于the revealing module pattern的概念。
您不应该使用 $.extend
进行继承,您应该在 class 的定义中立即声明继承,而不是稍后在 init
函数中声明继承。
另外,您的“增强型车辆超级-class 与子class”似乎真的很倒退。需要“复制 Vehicle 对象,因此它保持不变”并且您正在从 vehicle
而不是从 [= 创建 ferrari
实例来强调这一点16=].
我建议使用两个辅助函数:
function inherit(superClass, props, proto) {
return {
props: $.extend(Object.create(superClass.props), props),
proto: $.extend(Object.create(superClass.proto), proto)
};
}
function create(template) {
return Object.create(template.proto, template.props);
}
你可以像这样使用
var Vehicle = {
props : { 'colour' : {value:'black'}, 'wheels' : {value:4} },
proto : { 'drive' : function(){console.log('drive ' + this.colour + ' ' + this.wheels);} }
};
var Ferrari = inherit(Vehicle, {
'colour' : {value:'red'},
'seats' : {value:2}
}, {
'fast' : function(){console.log('ferrari power ' + this.colour + ' ' + this.wheels + ' ' + this.seats);}
});
var ferrari = create(Ferrari);
ferrari.drive();
ferrari.fast();
除了这些问题,你的模式还不错。使用纯原型继承是一种既定的模式。您可以通过向模板对象 (classes) 添加初始化函数来修改它,例如命名为.constructor
,您又回到了典型 class 模式的力量。