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

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

问题描述

我一直在使用模块模式,但最近开始想要将功能和属性混合到其中以增加代码重用。我已经阅读了一些关于这个问题的好的资源,但是对于最好的方法仍然有点不确定。这是一个模块:

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

//constructor
function module(){}

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

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

返回模块;
}

这里是一个mixin对象:

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

理想情况下,我想混合使用其他对象的一些方法作为私有方法和一些公共方法,所以我可以调用一些扩展功能,一个param为private/public。那么,那个

  mixin(myModule,myMixin,private); 

通过调用mixinMethod1()并具有正确的范围,使myModule中的myMixin方法可用,并且: / p>

  mixin(myModule,myMixin,public); 

通过调用module.mixinMethod1()并具有正确的范围,使myModule中的myMixin方法可用>

我已经尝试使用一种将属性从一个原型复制到另一个原型的方法,我已经尝试使用下划线extends方法将对象的属性从一个复制到另一个,以及各种各样的事情之间。在这一点上,我认为我有一些关于范围和原型的转变,并且会喜欢在使用模块模式时如何最好地做这样的mixin的方向。请注意,myMixin的对象不管什么(无论是为原型添加函数还是向模块添加),我只是想找出一些方法来使其工作。



谢谢!

解决方案


所以[一些代码]使myMixin myModule中的方法只需调用mixinMethod1()并具有正确的范围


这是不可能的。您不能通过调用函数来修改范围,特别是不能从外部修改。另请参见可以在JavaScript中的导入变量?



所以,你可以执行哪些



从模块之外



没有任何私人范围的模块功能。而且你不能使用模块的私有功能。您可以使用方法(最常见的)扩展其原型,甚至可以装饰其构造函数。在这些内部,您可以使用自己的私有函数,完全是静态的或类特定的。

  var myMixin = (){
//所有类 - 非特定但mixin-local
var staticMixinVariables,...;
函数globalPrivateFunction(){...}
function staticMethod(){...}

返回函数(mod){
//所有类别特定
//也使用上面的本地人
mod.staticHelper = function(){staticMixinVariable ...};
mod.prototype.mixinMethod1 = staticMethod;
mod.prototype.mixinMethod2 = function(){...};
...
};
})();

//示例:
myMixin(SomeClass)



从在模块中



在模块代码本身中使用mixin可以提供更大的灵活性。

  var myMixin =(function(){
//所有类 - 非特定但是mixin-local
...
return {
publicHelper1:function(){...},
publicHelper2:function(){...},
decorateInstance:function(o){
o。 xy = ...;
},
extendPrototype:function(proto){
//所有类别特定的
//也使用上面的本地人
proto.mixinMethod1 = staticMethod;
proto.mixinMethod2 = function(){...};
...
}
};
})();

使用这样的界面,很容易构造一个使用它作为mixin的类(不是继承自它):

  var myClass =(function(){
function Constructor(){
myMixin.decorateInstance(this);
...
}
构造方法.prototype.method1 = function(){myMixin.publicHelper1()...};
构造方法.prototype.method2 =函数(){...};
myMixin.extendPrototype(Constructor.prototype);
Constructor.myHelper = myMixin.publicHelper2; //显式重新导出
return构造函数;
}) ();

但是,mixin将永远不会访问私有类变量,也不能呈现私有,类专用API。然而,我们可以使用依赖注入来明确地提供该访问(并且有一个混合工厂生效):

  var myClass =( function(){
var ... //私有类函数和变量
var mixer = myMixin(privateClassHelper,
privateClassVariable,
函数setPrivateVar(x){...},

$ b var myHelper = mixer.customHelper,... // localaliases
function构造函数(localX){
mixer.decorateInstance(this,localX);
...
}
... //进一步使用类专用私有混音器
return构造函数;
})();






上面显示的所有技术都不需要使用每个mixin,只需选择你需要的。并不是所有可能的技术都显​​示在上面的例子中,也可以:-) mixin模式也可以应用于普通模块或其声明内,上面的例子只显示了具有原型的类。


对于一些很好的例子,和(无状态)特征,(状态)Mixins和他们的特权对手之间的理论区别,可以看一下本演示


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;
}

And here is a mixin object:

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");

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

mixin(myModule, myMixin, "public");

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

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.

Thank!

解决方案

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

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.

So, what can you do?

From outside the 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)

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

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

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


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 mixins的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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