强制函数上的参数而不声明它们

时间:2013-02-18 10:01:17

标签: javascript closures ecmascript-5

我对此做了一些研究,我不太希望这是可能的,但也许你们中间有一个JS向导知道如何解决这个问题。

我有一个像这样的JS函数:

{
    loadConfiguration: function(){
      theConfig.oneConfigOption = true;
      theConfig.anotherConfigOption = false;
    }
}

这是旧软件部分中的一种界面。截至目前,theConfig一直是全局变量。由于我不喜欢全局变量,我想从函数外部定义theConfig对象。

问题是,出于向后兼容性原因,函数的签名必须始终保持function(),并且需要设置对象的引用必须始终命名为theConfig,以便上述代码仍然是有效的配置加载器。 实际上我无法更改此代码块所在文件中的任何内容。

我可以改变的唯一地方是调用函数的位置(因为它在另一个文件中调用,可以从一个版本更新到另一个版本:

loadConfiguration();

我可以在这里做任何事情..封装函数,闭包或类似的东西。所以我的问题是,您能想出一种方法来强制theConfig loadConfiguration的引用指向我在调用函数时定义的对象而不用更改其签名吗?

1 个答案:

答案 0 :(得分:0)

我真的不确定你的目标是什么,但如果你被允许摆脱theConfig(使用不是window.theConfig的版本),等等,然后你可以使用IIFE。

var funcs = {
    loadConfiguration : (function () {
        var theConfig = {};

        //or, if you prefer...
        theConfig = some.object.somewhere.else.config;
        return function () {
        // this now resolves to the `theConfig` which is in the closure
        // created by the IIFE
            theConfig.one = true;
        };
    }());
};

您甚至可以使用该IIFE传递theConfig的位置。这里要注意的重要一点是theConfig 必须在这些IIFE RUN之前存在

loadConfiguration : (function (theConfig) {
    return function () { theConfig.x = 3; };
}(newConfigObject))

如果这些都不是您想要的,那么请更加具体地说明您希望从中得到什么。

修改

根据你的更新,我有一个可怕的,可怕的想法,理论上有效 这很难看,它是忍者,而且这不是我必须放在最终产品中的东西。
也就是说,它应该是非常可预测的, *尽管你需要更换的功能不需要访问关闭* - this可以通过电话或申请被黑客攻击,但是如果函数试图访问其他全局的东西(或者更糟糕的是,在闭包中定义,虽然它看起来不像),那么也需要导入。

看看:     //你的“loadConfig”目前居住的地方     var codeblock = {         //我们要交换函数的函数         target_func:function(){             theVar.prop = 1;             theVar.attr = 2;         }     };     //我们想要使用的新配置对象     var alternate = {         config:{}     };

// this whole thing would get injected somewhere into the page
// put it where you're about to fire your stuff
(function () {
    // the name of the variable doesn't actually matter right here
    // but I'm doing it for consistency
    var theVar = alternate.config,
        // grabbing the function as a string
        string = codeblock.target_func.toString(),
        // using regex to remove the `"function anonymous() {" + "}"` wrapper
        bare_func = string.replace(/^function[^{]+{/, "")
                          .replace(/}$/,""),

        // using the new Function constructor to pass in "theVar" (where the name matters)
        // the constructor doesn't accept closures, but any function that is created inside of the constructor does
        // so we return a new function (with the exact contents of the original function
        // but now, `theVar` is a parameter we're passing in 
        new_func = new Function ("theVar", "return function () {" + bare_func + "};"),
        // this is the new function returned from the constructor, and we're passing in "theVar"
        // again, name on the outside doesn't matter -- name in the `new Function` constructor DOES
        enclosed = new_func(theVar);

    // putting the function back where we stole it from
    codeblock.target_func = enclosed;
}());

如果我们之前运行codeblock.target_func();,则会设置

window.theVar.prop = 1;
window.theVar.attr = 2;

...但是如果我们现在调用这个函数......

codeblock.target_func();

alternate.config.prop;  // 1
alternate.config.attr;  // 2