这样 [一些代码] 只需调用 mixinMethod1() 就可以在 myModule 中使用 myMixin 方法并具有正确的范围
这不可能。您不能通过调用函数来修改作用域,尤其是不能从外部调用。另请参阅JavaScript 中是否可以使用变量?import
出于设计原因。
那么,你能做什么呢?
从模块外部
module
对函数的私有范围没有任何影响。显然,您不能使用模块的私有功能。你可以用方法扩展它的原型(这是最常见的),你甚至可以装饰它的构造函数。在这些函数中,您可以使用自己的私有函数,可以是完全静态的函数,也可以是特定于类的函数。
var myMixin = (function() {
// everything class-unspecific but mixin-local
var staticMixinVariables, …;
function globalPrivateFunction(){…}
function staticMethod(){…}
return function(mod) {
// everything class-specific
// also using the locals from above
mod.staticHelper = function() { staticMixinVariable … };
mod.prototype.mixinMethod1 = staticMethod;
mod.prototype.mixinMethod2 = function(){…};
…
};
})();
// Example:
myMixin(SomeClass)
从模块内部
在模块代码本身中使用 mixin 可以提供更大的灵活性。
var myMixin = (function() {
// everything class-unspecific but mixin-local
…
return {
publicHelper1: function(){…},
publicHelper2: function(){…},
decorateInstance: function(o) {
o.xy = …;
},
extendPrototype: function(proto) {
// everything class-specific
// also using the locals from above
proto.mixinMethod1 = staticMethod;
proto.mixinMethod2 = function(){…};
…
}
};
})();
有了这样的接口,就可以很容易地构造一个使用 this 作为 mixin 的类(而不是从它继承):
var myClass = (function() {
function Constructor() {
myMixin.decorateInstance(this);
…
}
Constructor.prototype.method1 = function() { myMixin.publicHelper1() … };
Constructor.prototype.method2 = function() { … };
myMixin.extendPrototype(Constructor.prototype);
Constructor.myHelper = myMixin.publicHelper2; // re-export explicitly
return Constructor;
})();
但是,mixin 永远无法访问私有类变量,也不能提供私有的、特定于类的 API。尽管如此,我们仍然可以使用依赖注入来显式地提供该访问(并且有一个生效的 mixin 工厂):
var myClass = (function() {
var … // private class functions and variables
var mixer = myMixin(privateClassHelper,
privateClassVariable,
function setPrivateVar(x) {…},
… );
var myHelper = mixer.customHelper, … // local "aliases"
function Constructor(localX) {
mixer.decorateInstance(this, localX);
…
}
… // further using the class-specific private mixer
return Constructor;
})();
并非上面显示的所有技术都需要在每个 mixin 中使用,只需选择您需要的技术即可。并非所有可能的技术都显示在上面的示例中,而且 :-) mixin 模式也可以应用于普通模块或在其声明中,上面的示例仅显示了带有原型的类。
有关一些很好的示例,以及(无状态)特征、(有状态)Mixin 及其“特权”对应物之间的理论区别,请查看此演示文稿。