AMD&xC0;Javascript对象上的点菜扩展方法

AMD&xC0;Javascript对象上的点菜扩展方法,javascript,js-amd,Javascript,Js Amd,我正在开发一个javascript库,希望在不同的模块中存储javascript对象上的可选方法组 这个库有两个模块,我们称它们为ModuleA和ModuleB。ModuleA导出一个类对象,我们称之为ClassA,它只有最小的核心功能。ModuleB定义了一组在ClassA原型上设置的可选方法 在不在库中的第三个模块ModuleC中,我希望: 如果我只导入ModuleA并实例化ClassA,我知道我可以使用“InstanceA.MethodA(…)”访问InstanceA上的所有Module

我正在开发一个javascript库,希望在不同的模块中存储javascript对象上的可选方法组

这个库有两个模块,我们称它们为ModuleA和ModuleB。ModuleA导出一个类对象,我们称之为ClassA,它只有最小的核心功能。ModuleB定义了一组在ClassA原型上设置的可选方法

在不在库中的第三个模块ModuleC中,我希望:

  • 如果我只导入ModuleA并实例化ClassA,我知道我可以使用“InstanceA.MethodA(…)”访问InstanceA上的所有ModuleA方法。(其他方法也可以在InstanceA上定义)

  • 如果我同时导入ModuleA和ModuleB并实例化ClassA,我知道我可以使用'InstanceA.MethodA(…)'和'InstanceA.MethodB(…)'访问InstanceA上的所有ModuleA方法以及ModuleB方法

我已经考虑了一些解决方案,但不确定是否有更好的方法来实现这一点。以下是我所考虑的:

模块B更改类别A模块B导入模块A的工厂并更改类别A。这些变化能保证持续下去吗?AMD是否保证在一个环境中导入相同的模块总是返回相同的对象

ModuleB返回修改后的ClassAModuleB扩展ClassA并返回新对象。在本例中,这可能只适用于两个模块,但对于多个可选方法模块又如何呢

如果您遇到类似情况,请告诉我您的解决方案。

以下是我的方法:

// Module A - Define ClassA
define(function() {
    function ClassA() {}
    ClassA.prototype.methodA = function() {};
    return ClassA;
});

// Module B - Extend
define(function() {
    return function(ClassToExtend) {
         ClassToExtend.prototype.methodB = function() { };
    };
});

// Module C - Sticking
define(function(require) {

    // Define ClassA
    var ClassA = require("module_a");

    // Extend ClassA with custom methods of ModuleB
    require("module_b")(ClassA);

    // Instanciate extended ClassA
    var InstanceA = new ClassA();
}

顺便说一句,这两种方法都有效。然而,据我所知,第一种方法依赖于非标准行为。我测试的模块加载实现保留了加载模块的缓存版本。然而,AMD规范似乎没有任何关于模块定义副作用的说明。如果这是错误的,请纠正我。Dojo AMD Loader:
define
还有两个可能不会立即显现的重要特性:1。模块创建是惰性和异步的,并且在调用
define
时不会立即发生。这意味着在某些运行的代码实际需要该模块之前,不会执行工厂,也不会解析该模块的任何依赖项。在模块名称空间中输入模块值后,不会在每次需要时重新计算该值。在实际层面上,这意味着工厂只被调用一次,返回值被缓存并在使用给定模块的所有代码之间共享。(注意:dojo加载器包括非标准函数
require.undef
,该函数用于取消模块值的定义。)注意:require.js还具有
require.undef(mid)
,这样您就可以丢失加载模块的缓存版本。我并没有真正考虑过这种方法,但它看起来不错,并且使扩展更加明确。另外需要注意的是,我在ModuleB(扩展模块)中添加了检查,以确保不会覆盖现有属性。结合phusick所描述的模块加载逻辑,这一点非常有效。