1 回答

TA貢獻(xiàn)1785條經(jīng)驗(yàn) 獲得超8個(gè)贊
前言
OP 正在尋找的可能解決方案背后的機(jī)制仍然是 OO,就像 OO 一樣;畢竟,人們正在處理的是通過調(diào)用 javascript 函數(shù)進(jìn)行對(duì)象組合(或?qū)ο?類型擴(kuò)充)。Eric Elliott -功能性 mixin - 和 Douglas Crockford -功能性繼承- 每個(gè)都很好地解釋了他們的方法。他們可能錯(cuò)過了命名/標(biāo)簽。在我看來,它應(yīng)該像基于函數(shù)的 mixin一樣簡單。JavaScript 開發(fā)人員之間的混淆會(huì)減少,因?yàn)楹瘮?shù)式術(shù)語將不再指向或誤導(dǎo)?The Land of FP?。
JavaScript 的強(qiáng)大功能function來自于它的每一個(gè)能力,第一是通過創(chuàng)建閉包來保持范圍,第二是通過它的調(diào)用方法之一訪問上下文并this提供前者。在第 3 位,它本身是一個(gè)可以傳遞的一流對(duì)象,它只是對(duì)完整的包進(jìn)行了四舍五入。callapply
方法
OP 的問題是如何實(shí)現(xiàn)模塊化行為,該行為依賴于由另一個(gè)行為封裝的狀態(tài),可以通過傳遞此狀態(tài)來解決。這種狀態(tài)不一定要公開展示。
Eric 和 Douglas 的概念將通過實(shí)際應(yīng)用而得到尊重/認(rèn)可。
在我看來,JavaScript 中的模塊化可組合行為始終應(yīng)該由一個(gè)函數(shù)提供,該函數(shù)既不應(yīng)該通過new關(guān)鍵字調(diào)用,也不應(yīng)該由調(diào)用運(yùn)算符調(diào)用...... (),但它總是必須應(yīng)用于/應(yīng)用于其他對(duì)象/通過call或類型apply。
具有共享但受保護(hù)(本地范圍)飛行狀態(tài)的 OP 示例代碼...
function withFlightStateAlteringFlightCapability(state) {
const flightCapableType = this;
flightCapableType.fly = () => {
state.flying = true;
return flightCapableType;
};
flightCapableType.land = () => {
state.flying = false;
return flightCapableType;
};
flightCapableType.isFlying = () => state.flying;
return flightCapableType;
}
function withFlightStateDependedEggLayingBehavior(state) {
const oviparousType = this;
oviparousType.layEgg = () => {
let returnValue;
// if (!this.isFlying()) {
if (!state.flying) {
returnValue = 'Laying egg...'
}
return returnValue;
};
return oviparousType;
}
function withMetaBehavior(label, behavior) {
this[label] = behavior;
}
class Duck {
constructor() {
// - glue code wrapped by constructor.
// - type will feature a class signature.
// - `state` gets preserved by the closure that is created with each instantiation.
// local state (shared and protected)
const state = {
flying: false
};
const duck = this;
withFlightStateAlteringFlightCapability.call(duck, state);
withFlightStateDependedEggLayingBehavior.call(duck, state);
withMetaBehavior.call(duck, 'quack', () => 'Quaaack...Quaaack...');
}
}
const duck = new Duck;
function createDuckAlikeType() {
// - glue code wrapped by factory function.
// - type will be an augmented but ordinary `Object` type.
// - `state` gets preserved by the closure that is created with each invocation of the factory.
// local state (shared and protected)
const state = {
flying: false
};
const type = {};
withFlightStateAlteringFlightCapability.call(type, state);
withFlightStateDependedEggLayingBehavior.call(type, state);
withMetaBehavior.call(type, 'quack', () => 'Quack!');
return type;
}
const duckAlikeType = createDuckAlikeType();
console.log('composed "real duck" : ', duck);
console.log('composed "duck alike type" : ', duckAlikeType);
console.log('\nduck.fly() ...');
duck.fly();
console.log('\nduck.isFlying() ? ', duck.isFlying());
console.log('duckAlikeType.isFlying() ? ', duckAlikeType.isFlying());
console.log('\nduck.layEgg() ? ', duck.layEgg());
console.log('duckAlikeType.layEgg() ? ', duckAlikeType.layEgg());
console.log('\nduck.land().layEgg() ? ', duck.land().layEgg());
console.log('duckAlikeType.fly().layEgg() ? ', duckAlikeType.fly().layEgg());
console.log('\nduck.isFlying() ? ', duck.isFlying());
console.log('duckAlikeType.isFlying() ? ', duckAlikeType.isFlying());
console.log('\nduck.quack() ? ', duck.quack());
console.log('duckAlikeType.quack() ? ', duckAlikeType.quack());
.as-console-wrapper { max-height: 100%!important; top: 0; }
添加回答
舉報(bào)