如何使用字符串引用闭包,就像我在不使用 eval 的情况下使用成员函数一样



我们在许多文件中拆分了一些js代码。我们有一个核心文件,它定义了许多其他 js 文件使用的代码。

目前我们有这样的东西:

核心.js:

window.mycore = function() {
    var myfunction1 = function() {
    };
    var myfunction2 = function() {
    };
    var myfunction3 = function() {
        //..
        var a =  myfunction1(b);
        //..        
    };
    //...
    // many "myfunction"
    //...
    var myfunctionN = function() {
    };
    var publish = function() {
        for(var i = 0; i < arguments.length; i++) {
            try {
                window.mycore[arguments[i]] = eval('(' + arguments[i] + ')');
            }
            catch(e) {
                Log.err(600, arguments[i], e);
            }
        }
    };
    publish("myfunction1", "myfunction7", "myfunction8",/*...*/"myfunctionM")
}

应用.js:

// ...
// ...
var result = window.core.myfunction1("myparam");
// ...
// ...

请注意,没有核心方法被声明为 window.core 对象的成员。相反,它们通过发布函数附加到核心对象。

这有一些优点:

    核心
  • 代码可以引用任何核心函数,而无需编写"window.core"。
  • 我们避免写"var myfunction = window.mycore.myfunction = function(( ..."在每个公共函数声明中
  • 公开的方法可以看到集中式的。

但是,在使用代码分析工具时,在发布函数中使用 eval 给我们带来了问题,因为它们不倾向于理解 eval 声明。

所以,这是我的问题。这是改进此代码的更好方法,因此我们可以保留上述优点,但消除 eval 声明。我知道向发布函数发送一些名称/值对的解决方案,例如 publish({'myfunction1': myfunction1}, ...(,但我也想避免函数名称重复。考虑到我不是在寻找根本性的改变,因为已经写了很多代码。

谢谢!

我不确定我是否完全理解您使用"发布"方法的原因,但是您有什么理由不从构造函数返回具有正确函数的对象吗?

即:

window.mycore = (function() {
   var myFunc1 = function(a) {
      alert(a);
   };
   var myFunc2 = function(b) {
      // call to other function in the same scope
      myFunc1(b);
   }
   ...
   // at the end just expose the public members you want
   return {
      myFunc1: myFunc1,
      myFunc2: myFunc2
   };
})();

window.mycore = (function() {
   return {
      myFunc1: function(a) {
         alert(a);
      },
      myFunc2: function(b) {
         this.myFunc1(b);
      }
   };
})();

或者,另一种最终得到相同对象的方法:)......与往常一样,有不同的方式到达那里

(function(){
    var o = {};
    o.func1 = function(a) {
        alert(a);
    }
    o.func2 = function(b) {
        this.func1(b);
    }
    window.mycore = o;
})();

因此,在基本层面上,我认为将这些命名空间编写为对象会有益于您。但这是一个完全不同的主题。(并且它基于您不想进行大量重构的事实而取消资格(。

话虽如此,我的第一个想法是,您可能可以通过使用 .call().apply() 方法来回避对 eval 的需求。它们允许您做的是将函数调用从您的函数名称中链接出来。但这不适用于您为发布函数提供的"字符串"。

因此,在谷歌搜索之后,这就是您从字符串执行函数的方式:

var fn = window[settings.functionName];
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}

https://stackoverflow.com/a/912642/680578

就个人而言,我更喜欢@Jaime的方法,但也许你可以做一些类似的事情

window.mycore = function() {
    function myfunction1() {
    };
    function myfunction2() {
    };
    function myfunction3() {
       //..
       var a =  myfunction1(b);
       //..        
    };
    //...
    // many "myfunction"
    //...
    function myfunctionN() {
    };
    var publish = function() {
       for(var i = 0; i < arguments.length; i++) {
          try {
             window.mycore[arguments[i].name] = arguments[i];
          }
          catch(e) {
             Log.err(600, arguments[i].name, e);
          }
       }
    };
    publish(myfunction1, myfunction7, myfunction8,/*...*/myfunctionM);
}

最新更新