[英]How do I share “constructor” functionality in Crockford's new constructor pattern?
我现在已经多次在无类OOP上观看了这个问题的视频,而我在将这个应用到现实世界的例子中时遇到了麻烦。
Crockford的新构造函数模式如下所示:
function constructor(spec) {
let {member} = spec,
{other} = other_constructor(spec),
method = function () {
// accesses member, other, method, spec
};
return Object.freeze({
method,
other,
});
}
其中spec
是一个选项哈希,结果对象公开了关闭所有内部成员的方法。 忽略解构(因为这可以在现今的JS中以长篇形式完成) ,我如何在现实世界的例子中应用这种模式?
我目前有一个带有基类Module(model, id)
的库,其中model
是一些引导数据。
// constructor, original flavor
function Module(model, id) {
this.id = id;
this.model = model;
}
然后我有几种类型的模块继承自这个父Module
。 在Crockford的模式下,我会把它作为“构造函数”:
// constructor, Crockford's Cool Ranch
function module(spec) {
let id = spec.id,
model = spec.model;
return Object.freeze({});
}
我如何使用Crockford的模式(它似乎根本不使用继承,而是从多个源组成一个对象) 在多种模块之间共享这种基本结构 ?
我知道id
和model
将成为每个模块的“构造函数”中的局部变量; 我基本上问如何避免使用Crockford模式为每种模块重复model = spec.model
。
Crockford所说的“无类继承”实际上仍然是原型继承。 实际上,有两种 类型的原型继承机制:
这就是我传统上编写面向对象的JavaScript代码的方法:
var Aircraft = defclass({ constructor: function (model, speed) { this.model = model; this.speed = speed; }, describeAircraft: function () { alert("The " + this.model + " flies at " + this.speed + " speed."); } }); var FighterAircraft = extend(Aircraft, { constructor: function (model, speed, radar) { Aircraft.call(this, model, speed); this.radar = radar; }, describeFighterAircraft: function () { this.describeAircraft(); alert("It has a " + this.radar + " radar signature."); } }); var superFlanker = new FighterAircraft("Super Flanker", "Mach 2.25", "low"); superFlanker.describeFighterAircraft();
<script> function defclass(prototype) { var constructor = prototype.constructor; constructor.prototype = prototype; return constructor; } function extend(constructor, properties) { var prototype = Object.create(constructor.prototype); for (var name in properties) prototype[name] = properties[name]; return defclass(prototype); } </script>
这就是Crockford倡导编写面向对象的JavaScript代码的方式:
var superFlanker = FighterAircraft({ model: "Super Flanker", speed: "Mach 2.25", radar: "low" }); superFlanker.describeFighterAircraft();
<script> function Aircraft(spec) { var model = spec.model; var speed = spec.speed; function describeAircraft() { alert("The " + model + " flies at " + speed + " speed."); } return Object.freeze({ model: model, speed: speed, describeAircraft: describeAircraft }); } function FighterAircraft(spec) { var aircraft = Aircraft(spec); var model = spec.model; var speed = spec.speed; var radar = spec.radar; function describeFighterAircraft() { aircraft.describeAircraft(); alert("It has a " + radar + " radar signature."); } return Object.freeze({ model: model, speed: speed, radar: radar, describeFighterAircraft: describeFighterAircraft }); } </script>
Crockford的连接原型继承方法有很多重复。 另一种选择是:
var aircraft = mixin({ describeAircraft: function () { alert("The " + this.model + " flies at " + this.speed + " speed."); } }); var fighterAircraft = mixin(aircraft, { describeFighterAircraft: function () { this.describeAircraft(); alert("It has a " + this.radar + " radar signature."); } }); var superFlanker = fighterAircraft({ model: "Super Flanker", speed: "Mach 2.25", radar: "low" }); superFlanker.describeFighterAircraft();
<script> function mixin() { var length = arguments.length; var index = 0; while (index < length) { var properties = arguments[index++]; for (var name in properties) constructor[name] = properties[name]; } return Object.freeze(constructor); function constructor(object) { for (var name in constructor) object[name] = constructor[name]; return Object.freeze(object); } } </script>
this
使用mixins 是的,你可以使用mixins而不使用this
。 但是,我不明白你为什么要这样做:
var aircraft = mixin({ describeAircraft: function (aircraft) { alert("The " + aircraft.model + " flies at " + aircraft.speed + " speed."); } }); var fighterAircraft = mixin(aircraft, { describeFighterAircraft: function (fighterAircraft) { fighterAircraft.describeAircraft(); alert("It has a " + fighterAircraft.radar + " radar signature."); } }); var superFlanker = fighterAircraft({ model: "Super Flanker", speed: "Mach 2.25", radar: "low" }); superFlanker.describeFighterAircraft();
<script> function mixin() { var length = arguments.length; var index = 0; while (index < length) { var properties = arguments[index++]; for (var name in properties) constructor[name] = properties[name]; } return Object.freeze(constructor); function constructor(object) { for (var name in constructor) { var value = constructor[name]; object[name] = typeof value === "function" ? value.bind(null, object) : value; } return Object.freeze(object); } } </script>
有很多理由喜欢组合而不是继承 :
我能想到的唯一缺点是,如果原型被修改,那么更改将不会反映在其实例上。 但是,无论如何都没有充分的理由改变原型。 因此,我的mixins都被冷冻了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.