使用模块模式时的 Javascript 混合 [英] Javascript mixins when using the module pattern

查看:16
本文介绍了使用模块模式时的 Javascript 混合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用模块模式有一段时间了,但最近开始想要将函数和属性混合到它们中以增加代码重用.我已经阅读了一些关于这个主题的好资源,但对于最佳方法仍然有点不确定.这是一个模块:

I've been using the module pattern for a while, but recently have started wanting to mix in functions and properties into them to increase code re-use. I've read some good resources on the subject, but still am a bit uncertain as to the best approach. Here is a module:

var myModule = function () {
    var privateConfigVar = "Private!";

    //"constructor"
    function module() {}

    module.publicMethod = function () {
        console.log('public');
    }

    function privateMethod1() {
        console.log('private');
    }

    return module;
}

这是一个混合对象:

var myMixin = function () {};
Mixin.prototype = {
    mixinMethod1: function () {
        console.log('mixin private 1');
    },
    mixinMethod2: function () {
        console.log('mixin private 2');
    }
};

理想情况下,我想将来自其他对象的一些方法作为私有方法和一些作为公共方法混合,以便我可以调用一些扩展"函数,参数为私有"/公共".所以,那

Ideally, I'd like to mix-in some methods from other objects as private methods and some as public methods, so that I could call some "extend" function, with a param as "private"/"public". So, that

mixin(myModule, myMixin, "private");

只需调用 mixinMethod1() 就可以在 myModule 中使用 myMixin 方法并具有正确的作用域,并且:

makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope, and:

mixin(myModule, myMixin, "public");

通过调用 module.mixinMethod1() 使 myMixin 方法在 myModule 中可用并具有正确的作用域

makes the myMixin methods available within myModule by calling module.mixinMethod1() and have correct scope

我尝试使用一种方法将属性从一个原型复制到另一个原型,我尝试使用下划线扩展方法将对象的属性从一个复制到另一个,以及介于两者之间的各种内容.我想我在这一点上对范围和原型有点转变,并且希望在使用模块模式时如何最好地做这样的 mixin 的一些指导.请注意,对象 myMixin 是什么样子并不重要(无论是向原型添加函数,还是模块本身),我只是想找出某种方法使其工作.

I've tried using a method that copies properties from one prototype to another, I've tried the underscore extend method to copy properties of the object from one to to the other, and various things in between. I think I'm a bit turned around regarding scope and prototypes at this point, and would love some direction as to how best to do mixins like this when using the module pattern. Note that it doesn't matter what the object myMixin looks like (whether adding functions to the prototype, or a module itself), I'm just trying to figure out some way to make it work.

谢谢!

推荐答案

这样 [一些代码] 就可以通过调用 mixinMethod1() 使 myMixin 方法在 myModule 中可用并具有正确的作用域

So that [some code] makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope

那是不可能的.您不能通过调用函数来修改作用域,尤其不能从外部调用.另请参阅是否可以在 JavaScript 中import 变量? 出于设计原因.

That's impossible. You cannot modify a scope by calling a function, especially not from outside. See also Is it possible to import variables in JavaScript? for the design reasons of that.

那么,你做什么?

module 函数的私有范围没有任何内容.显然,您不能使用模块的私有函数.你可以用方法(这是最常见的)扩展它的原型,你甚至可以装饰它的构造函数.在这些函数中,您可以使用自己的私有函数,可以是完全静态的函数,也可以是特定于类的函数.

Nothing to the private scope(s) of module functions. And you cannot use the private functions of the module, obviously. You can extend its prototype with methods (which is the most common), you can even decorate its constructor function. Within those, you can use your own private functions, either completely static ones or class-specific ones.

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 可以提供更大的灵活性.

From within the module

Using the mixin in the module code itself can allow for much greater flexibility.

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(){…};
            …
        }
    };
})();

有了这样的接口,很容易构造一个使用它作为 mixin 的类(不是从它继承):

With such an interface, it becomes easy to construct a class that is using this as a mixin (not inheriting from it):

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 工厂):

However, the mixin will never have access to the private class variables, nor can it present a private, class-specific API. Still, we can use dependency injection to provide that access explicitly (and having a mixin factory in effect):

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 模式可以应用于普通模块或其声明中,上面的示例仅显示了具有原型的类.


Not all techniques shown above need to be used in every mixin, just choose the ones you need. Not all possible techniques are shown in the above examples, also :-) The mixin pattern can be applied onto a plain module or inside its declaration as well, the above examples have only shown classes with prototypes.

关于一些很好的例子,以及(无状态)特征、(有状态)混合和它们的特权"对应物之间的理论区别,看看 本演示文稿.

For a few good examples, and a theoretical distinction between (stateless) Traits, (stateful) Mixins and their "privileged" counterparts, have a look at this presentation.

这篇关于使用模块模式时的 Javascript 混合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆