[英]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.