如何在不使用eval的情况下使用成员函数使用字符串引用闭包?

时间:2012-05-10 14:27:47

标签: javascript

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

目前我们有这样的事情:

core.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")
}

app.js:

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

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

这有一些优点:

  • 核心代码可以引用任何核心功能,而无需编写“window.core。”
  • 我们避免在每个公共函数声明中写“var myfunction = window.mycore.myfunction = function()...”
  • 暴露的方法可以看作是中心的。

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

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

谢谢!

3 个答案:

答案 0 :(得分:2)

我不确定我完全理解使用&#34;发布&#34;方法,但有没有理由你不只是从构造函数返回一个具有正确函数的对象?

即:

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;

})();

答案 1 :(得分:0)

所以,从根本上讲,我认为将这些名称空间写成对象会让你受益。但这完全是一个完全不同的主题。 (并且基于您不想进行大量重构这一事实而取消资格)。

话虽如此,我的第一个想法是,你可以可能使用.call().apply()方法来回避对eval的需求。它们允许您执行的操作是将函数调用链接到函数名称之外。但这并不适用于你正在为你的发布功能提供的“字符串”。

所以在谷歌搜索之后,这是你从字符串中执行函数的方式:

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

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

答案 2 :(得分:0)

就个人而言,我更喜欢@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);
}