2

我对打电话或申请更改this参考不感兴趣。只是为了我自己的兴趣,我正在尝试另一种 javascript 的 require 技术,这将使定义更清晰,目标是不必为我的定义传递数组或双重引用模块名称。

我有一个在函数上使用 toString 和 eval 的示例解决方案(只是一个概念证明),但我想知道是否有更安全或更有效的方法来做到这一点。

// Sample module libraries (would probably be in their own files)
someModules = { 
    testModule: {test: function(){console.log("test from someModule")}},
    anotherModule: { doStuff: function(){console.log("Doin stuffs!");}}
};

sampleRequire = function() {

    // Load the modules
    for (var i=arguments.length-2; i>=0; --i){

        // Create a local variable reference to the module
        eval ('var '+arguments[i]+' = someModules.'+arguments[i].toString());
    }

    // Redefine the programmer's function so that it has my local vars in its scope
    eval("var fn = "+arguments[arguments.length-1]);

    return fn;
}

// Main code...
sampleRequire( 'testModule', 'anotherModule',
    function(){ 
        testModule.test();
        anotherModule.doStuff();
    }
)();

编辑:

Pointy 提出了一个很好的观点,即这将完全破坏 main 函数的范围,这通常是不可接受的。理想情况下,我希望看到模块变量被添加到函数的范围内,而不会破坏它的其他范围变量(模块名称除外——程序员必须知道不要对两件事使用相同的名称)。我打赌这可能是不可能的,但我仍然希望看到一些想法。

另一个目标是灵活地执行此操作,而不必将每个模块的参数添加到主函数。否则,我们将回到 CommonJS 样式的第一方(我不是想与之抗争,只是对范围感到好奇!)。

4

3 回答 3

1

我倾向于说“你做错了”。即使可以,使用未声明的变量也不是一个好主意。

这是另一个将模块写入全局对象的技巧。但是,这可能会对从主函数调用的方法产生副作用。

sampleRequire = function() {

    var cache = {};
    var moduleNames = [].slice.call(arguments);
    var fn = moduleNames.pop();

    return function () {
        var result, name, i;
        // export modules to global object
        for (i = 0; i < moduleNames.length; i++) {
            name = moduleNames[i];
            cache[name] = window[name]; // remember old values
            window[name] = someModules[name];
        }
        result = fn.apply(null, arguments);
        // restore original global stuff
        for (i = 0; i < moduleNames.length; i++) {
            name = moduleNames[i];
            window[name] = cache[name];
        }
        return result;
    };
}

我还尝试了一些关于with关键字的魔法,它基本上是为你想要的而制作的。eval但是,在这种情况下,它似乎无法正常工作。

于 2012-04-06T08:46:38.797 回答
0

我想不出任何其他方式来做你所追求的。我还怀疑这可能是少数eval邪恶的用例之一。但请记住,模块可能依赖于它们的作用域,这可能会破坏它们。

于 2012-04-05T15:30:44.513 回答
0

怎么样:

someModules = { 
  testModule: {test: function(){console.log("test from someModule")}},
  anotherModule: { doStuff: function(){console.log("Doin stuffs!");}}
};

function requireModules() {
  var all = [];
  for (var i = 0, l = arguments.length; i<l; i++) {
    all.push(someModules[i]);
  }
  return all;
}

(function(testModule,anotherModule){
  testModule.test();
  anotherModule.doStuff();
}).apply(null,requireModules('testModule','anotherModule'));
于 2012-04-05T15:32:11.970 回答