JavaScript:通过变量名查找变量的值,在这里eval可以接受吗?

时间:2019-12-06 19:42:31

标签: javascript reflection eval

警告:正如此处其他人所述,此问题是基于不灵活的客户要求。虽然问题是正确的,但如果可能的话,您绝对应该使用更简单的解决方案(例如:将设置放在单个对象中)!

我有一个要“注意”的变量数组。那就是:如果它们以前是在代码中定义的,那么我需要能够对它们的值进行操作。

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

我希望警报显示为example.com/?&a=foo

我已经看到大量其他答案,其中包括不使用eval函数的情况,而且我已经尝试了window[element]的使用,但没有成功。不必为我要检查的每个变量都编写if / else,最好怎么做?

2 个答案:

答案 0 :(得分:1)

假设您不能做其他事情,并且一切都在全局范围内,则可以不使用eval()而做。 (我很确定eval必须有一些有效的用例,但我不认为这是其中之一。)

由于您不应该信任这些变量的内容,因此不应该使用eval。如果您的客户选择受到影响怎么办? (或者仅仅是您的客户不知道他们在做什么。)

var css_color = 'tweet(document.cookie)';

您可以简单地利用以下事实:可以从全局范围访问变量:

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>

答案 1 :(得分:0)

这种问题的答案几乎总是“您正在考虑问题错了。”,例如这里。

您假设应该使用变量来完成此操作,这使您陷入只能使用eval()才能摆脱困境的困境。我了解客户可能要求提供常规变量,但是如果我是房屋建筑商,并且客户要求我用棉花糖盖房子,我会说“不”,那不是这样做的方法。

解决方案是从一开始就使用带有键和值的对象,这使您以后可以使用数组索引语法,而不是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);