1

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.com/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!

4

6 回答 6

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)

于 2013-11-05T20:45:44.040 回答
2

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 recommended. 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.

于 2013-11-05T20:43:51.020 回答
2

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];
});
于 2013-11-05T20:46:08.423 回答
2

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.

于 2013-11-05T20:54:26.223 回答
1

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.

于 2013-11-05T20:46:25.127 回答
1

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.

于 2013-11-05T20:51:11.467 回答