1 回答

TA贡献1785条经验 获得超8个赞
前言
OP 正在寻找的可能解决方案背后的机制仍然是 OO,就像 OO 一样;毕竟,人们正在处理的是通过调用 javascript 函数进行对象组合(或对象/类型扩充)。Eric Elliott -功能性 mixin - 和 Douglas Crockford -功能性继承- 每个都很好地解释了他们的方法。他们可能错过了命名/标签。在我看来,它应该像基于函数的 mixin一样简单。JavaScript 开发人员之间的混淆会减少,因为函数式术语将不再指向或误导»The Land of FP«。
JavaScript 的强大功能function来自于它的每一个能力,第一是通过创建闭包来保持范围,第二是通过它的调用方法之一访问上下文并this提供前者。在第 3 位,它本身是一个可以传递的一流对象,它只是对完整的包进行了四舍五入。callapply
方法
OP 的问题是如何实现模块化行为,该行为依赖于由另一个行为封装的状态,可以通过传递此状态来解决。这种状态不一定要公开展示。
Eric 和 Douglas 的概念将通过实际应用而得到尊重/认可。
在我看来,JavaScript 中的模块化可组合行为始终应该由一个函数提供,该函数既不应该通过new关键字调用,也不应该由调用运算符调用...... (),但它总是必须应用于/应用于其他对象/通过call或类型apply。
具有共享但受保护(本地范围)飞行状态的 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; }
添加回答
举报