【问题标题】:Alternative to using eval()替代使用 eval()
【发布时间】:2013-11-05 20:42:03
【问题描述】:

我听到很多关于 eval 函数是多么“邪恶”甚至是“误解”的传言,所以我决定从我的代码中删除它。问题是我不知道用什么替换它。

这是我当前代码的简要说明。我在开始时声明了一系列数组(以下示例中只有 2 个),然后基于按钮单击其中一个被加载到传递给函数的变量中。

这是一些基本的 HTML

<div class="button" data-name="button1">Button1</div>
<div class="button" data-name="button2">Button2</div>

和 JS(使用 jQuery)

var butName = null;
var eArray = null;
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];

    $(".button").mouseup(function(){
            /*give a butName*/
            butName = $(this).attr("data-name");

            /*give the array from the button*/
            eArray = eval(butName + "Logo");
    });

这样做会将数组分配给变量,而不仅仅是一个显示“butnameLogo”的字符串,这就是我使用 eval 的原因。但我希望摆脱这种情况。

我知道我可以向 html 添加一个新属性,然后为变量检索该属性,但我不想添加更多 html,因为我可以使用 JS 来完成。

我也尝试过制作一个加载了字符串的对象,如以下答案所示:https://stackoverflow.com/a/16038097/1621380 但这导致再次只是一个字符串,而不是分配变量。

想知道各位聪明人有没有更好的建议!

【问题讨论】:

  • 这是被问到最多的问题之一,但通常细节较少......
  • 您得到的答案将与您在其他问题中找到的答案相同。
  • 当你遇到一个系列时,把它做成一个数组(hashmap)!
  • 只是一个你可能感兴趣的快速提示——jQuery 解析任何数据属性——所以你可以使用$(this).data("name") 代替$(this).attr("data-name")(并使用$(this).data("name", "new value") 设置它)。它甚至根据需要将其从字符串转换为数字/对象/数组。总有一天可以帮到你。文档:(jQuery Docs)

标签: javascript jquery arrays eval


【解决方案1】:

替换

var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];

带有一个对象,其中的键是您的按钮名称:

var buttonLogos = {
    button1: ["..path/to/pic1.png","..path/to/pic2.png"],
    button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};

那么你可以简单地做而不是eval

eArray = buttonLogos[butName]

(或者buttonLogos[butName + "Logo"],如果你想调用键button1Logobutton2Logo,但我现在看不出重点,因为它们很好地包含在buttonLogos对象中)

【讨论】:

    【解决方案2】:

    使用一个对象:

    var butName = null;
    var buttonsLogos = {
          button1: ["..path/to/pic1.png", "..path/to/pic2.png"],
          button2: ["..path/to/pic3.png", "..path/to/pic4.png"]
    };
    
    $(".button").mouseup(function(){
        /*give a butName*/
        butName = $(this).attr("data-name");
    
        /*give the array from the button*/
        eArray = buttonsLogos[butName];
    });
    

    【讨论】:

      【解决方案3】:

      考虑将数据作为对象的属性提供,然后您可以通过范围控制对对象的访问,并且所有此类数据只需要一个(全局?)变量。

      如果需要全局作用域,那么:

      var dataObj = {
          button1Logo: ["..path/to/pic1.png","..path/to/pic2.png"],
          button2Logo: ["..path/to/pic3.png","..path/to/pic4.png"]
      }
      

      及以后:

      var eArray = dataObj[this.data-name + 'Logo'];
      

      您可能希望调用数据对象比 dataObj 更有意义的东西。

      【讨论】:

        【解决方案4】:

        最好的选择是定义一个包含所有按钮路径的对象:

        var buttons = {
            "1": ["..path/to/pic1.png", "..path/to/pic2.png"],
            "2": ["..path/to/pic3.png", "..path/to/pic4.png"]
        };
        $(".button").mouseup(function(){
          /* give a butName */
          var butName = $(this).attr("data-name");
        
          /* give the array from the button */
          var eArray = buttons[butName];
        });
        


        如果您的变量位于全局范围内,您可以使用 the bracket notation 来访问它们:
        eArray = window[butName + "Logo"];
        

        注意,不推荐使用此解决方案。第一个代码示例更简洁,更易于维护。

        想象一下您必须将所有代码移动到“更深”上下文(!= 全局上下文)的情况。什么都行不通了。

        【讨论】:

        • 不在全局上下文中定义变量会破坏这个解决方案。
        • @dystroy 你的原始答案(只有window[butName + "Logo"] 部分是(a)可能是错误的,(b)即使它是正确的也是一个坏主意!
        • @dystroy 我现在给了你一个赞成票(不,我的评论并不荒谬!)。这个答案也是CW,所以不要在意投票。
        • @dystroy "易于调整" -- 你确定吗?
        • @dystroy OP 可能确实在全局上下文中运行代码。这并不意味着我们应该提供依赖于这一事实的解决方案。
        【解决方案5】:

        您可以使用数组和数组索引很好地做到这一点。您根本不需要查找和使用变量名。甚至你的data- 属性也是不必要的。

        var eArray;
        var buttonLogos = [
            ["..path/to/pic1.png","..path/to/pic2.png"],
            ["..path/to/pic3.png","..path/to/pic4.png"]
        ];
        
        var buttons = $(".button").mouseup(function(){
            var idx = buttons.index(this);
        
            eArray = buttonLogos[idx];
        });
        

        这里的关键行是buttons.index(this)。该方法调用获取当前元素在$(".button")匹配的所有元素中的位置。然后我们使用这个索引从buttonLogos数组中选择相关元素。

        【讨论】:

          【解决方案6】:

          在这里使用eval,你走的是一条非常迂回的路线。

          你最好做这样的事情:

          var paths = {
              button1: ["..path/to/pic1.png","..path/to/pic2.png"],
              button2: ["..path/to/pic3.png","..path/to/pic4.png"]
          };
          
          $(".button").mouseup(function(){
              /*give the array from the button*/
              eArray = paths[$(this).attr("data-name")];
          });
          

          eval 只应在您需要执行代码(通常来自第 3 方源)时使用,即使这样也很少见。如果您发现自己说“我应该在这里使用 eval”,那么几乎肯定有更好的选择,您应该尝试找到它。

          【讨论】:

          • "你应该试着找到它。" ——于是他来到了这里:-)
          猜你喜欢
          • 1970-01-01
          • 2016-04-10
          • 2013-04-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多