admin管理员组

文章数量:1356233

I've heard a lot of rumblings about how "evil" or even "misunderstood" the eval function is, so I've decided to remove it from my code. The problem is I don't know what to replace it with.

Here's a quick rundown of my current code. I have a series of arrays (just 2 for the example below) declared at the beginning, and then based on a button click one of them gets loaded into a variable that is passed into a function.

Here's some basic HTML

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

and the JS (with 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");
    });

Doing it this way assigns the array to the variable and not just a string that says "butnameLogo" which is why I used eval. But I'm looking to get away from that.

I know I can add a new attribute to the html and just retrieve that for the variable but I don't want to add more html when I can possibly do it with JS.

I've also tried making an object with strings loaded into it as seen in this answer: but that resulted in just a string again, and not assigning a variable.

Wondering if you smart people have any better suggestions!

I've heard a lot of rumblings about how "evil" or even "misunderstood" the eval function is, so I've decided to remove it from my code. The problem is I don't know what to replace it with.

Here's a quick rundown of my current code. I have a series of arrays (just 2 for the example below) declared at the beginning, and then based on a button click one of them gets loaded into a variable that is passed into a function.

Here's some basic HTML

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

and the JS (with 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");
    });

Doing it this way assigns the array to the variable and not just a string that says "butnameLogo" which is why I used eval. But I'm looking to get away from that.

I know I can add a new attribute to the html and just retrieve that for the variable but I don't want to add more html when I can possibly do it with JS.

I've also tried making an object with strings loaded into it as seen in this answer: https://stackoverflow./a/16038097/1621380 but that resulted in just a string again, and not assigning a variable.

Wondering if you smart people have any better suggestions!

Share Improve this question edited May 23, 2017 at 12:21 CommunityBot 11 silver badge asked Nov 5, 2013 at 20:42 SpittalSpittal 7792 gold badges12 silver badges23 bronze badges 4
  • 1 It's one of the most asked questions but usually with less details... – Denys Séguret Commented Nov 5, 2013 at 20:43
  • The answer you get is going to be the same as the answer you found in that other question. – Blue Skies Commented Nov 5, 2013 at 20:43
  • 1 Whenever you encounter a series, make it an array (hashmap)! – ComFreek Commented Nov 5, 2013 at 20:43
  • 1 Just a quick tip you may be interested in - jQuery parses any data- attributes – so instead of $(this).attr("data-name") you could use $(this).data("name") (and set it using $(this).data("name", "new value")). It even converts it from string to number/object/array as appropriate. May help you one day. Docs: (jQuery Docs) – Shai Commented Nov 5, 2013 at 21:39
Add a ment  | 

6 Answers 6

Reset to default 8

Replace

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

with an object, where the keys are your button names:

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

Then instead of the eval you can simply do

eArray = buttonLogos[butName]

(or buttonLogos[butName + "Logo"] if you want to call the keys button1Logo and button2Logo, but I can't really see the point now that they are nicely contained within a buttonLogos object)

Use an object:

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];
});

Consider making the data available as properties of an object, then you can control access to the object through scope and only need one (global?) variable for all such data.

If global scope is needed, then:

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

and later:

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

You may want to call the data object something more meaningful than dataObj though.

The best option is to define an object which holds all our button paths:

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];
});


If your variables reside in the global scope, you could use the bracket notation to access them:

eArray = window[butName + "Logo"];

Note that this solution is not remended. The first code sample is much cleaner and more maintainable.

Imagine a situation where you would have to move all the code into a 'deeper' context (!= global context). Nothing would work anymore.

You can do this very nicely with arrays and array indexes. You needn't find and use variable names at all. Even your data- attributes are unnecessary.

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];
});

The key line in this is buttons.index(this). This method call gets the position of the current element among all the elements matched by $(".button"). We then use this index to select the relevant element from the buttonLogos array.

You're taking a very circuitous route by using eval here.

You'd be much better off doing something like this:

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 should only be used if you need to execute code (usually from a 3rd party source), and even that is rare. If you ever find yourself saying "i should use eval here", there's almost definitely a better alternative, and you should try and find it.

本文标签: javascriptAlternative to using eval()Stack Overflow