Reputation: 3171
WARNING: As other have stated here, this problem is based upon an inflexible customer requirement. While the question is valid, you should definitely use the simpler solutions (ex: putting your settings in a single object) if possible!
I have an array of variables I want to be "watching out" for. That is: if they were previously defined in the code, I need to be able operate on their values.
var a = 'foo'; // only a gets defined
// ...more code here... IMPORTANT: I can only control what comes BELOW this line!
var target = 'exmple.com/?';
var gets = ['a', 'b', 'c']; // these are the names of the variables I want to check for
gets.forEach(function(element) { // checking each one
if(typeof element !== 'undefined') { // if it's previously defined
target += "&"+element+"="+eval(element); // add `&a=foo` to target
}
});
alert(target);
I'd like the alert to be printing example.com/?&a=foo
I've seen the tons of other answers not to use the eval
function, and I have tried window[element]
in place without success. How would it be best to do this without having to write an if/else for every variable I want to check?
Upvotes: 0
Views: 66
Reputation: 65806
The answer to this kind of question is almost always "You're thinking about the problem wrong.", as is the case here.
You make the assumption that this should be done with variables and that backs you into the corner of only being able to use eval()
to get out of that corner. I understand that the customer may have asked for regular variables, but if I were a house builder and the customer asked me to build a house out of marshmallow, I'd say "no", that's not the way to do it.
The solution is to use an object with keys and values from the start, which allows you to use array indexing syntax later, instead of eval
.
// Keep the items you need to check in an object
var obj = {
a:'foo' // only a gets defined
}
var target = 'exmple.com/?';
var gets = ['a', 'b', 'c'];
// Check each array element
gets.forEach(function(element) {
// Objects can use array indexing syntax where a string is passed as the index
// because objects actually have keys, rather than numeric indexes
if(obj[element]) { // if it's previously defined
target += "&" + element + "=" + obj[element]; // add `&a=foo` to target
}
});
alert(target);
Upvotes: 0
Reputation: 18901
Assuming you can't do otherwise and everything lives in the global scope, you could do without resorting to using eval()
. (I'm pretty sure there must be some valid use cases for eval
but I don't think this is one is one of them.)
Since you shouldn't trust the content of these variables you shouldn't be using eval
. What if your customer options get compromised? (Or simply your customer doesn't know what they're doing.)
var css_color = 'tweet(document.cookie)';
You can simply leverage the fact that the variables will be accessible from the global scope:
const serialize_options = (...vars) =>
vars
.filter(v => typeof this[v] !== 'undefined')
.map(v => `${v}=${this[v]}`)
.join('&');
console.log(serialize_options('a'));
console.log(serialize_options('a', 'b'));
console.log(serialize_options('a', 'b', 'c'));
console.log(serialize_options('a', 'x', 'y'));
<script>
var a = '10';
var b = '20';
var c = '30';
</script>
Upvotes: 1