JavaScript: 通过名称查找变量的值,eval 在这里可以接受吗?
JavaScript: Finding a variable's value by its name, is eval acceptable here?
警告:正如此处其他人所述,此问题是基于不灵活的客户要求。虽然这个问题是有效的,但如果可能的话,您绝对应该使用更简单的解决方案(例如:将您的设置放在一个对象中)!
我有一个变量数组,我想成为 "watching out" 的变量。也就是说:如果它们之前在代码中定义过,我需要能够对它们的值进行操作。
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,最好的做法是什么?
这类问题的答案几乎都是"You're thinking about the problem wrong.",这里也是如此。
你假设这应该用变量来完成,这让你陷入了只能使用 eval()
走出那个角落的困境。我知道客户可能要求提供常规变量,但如果我是一名房屋建筑商并且客户要求我用棉花糖建造房屋,我会说 "no",这不是这样做的方法。
解决方案是从一开始就使用带有键和值的对象,这样您以后就可以使用数组索引语法,而不是 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);
假设您别无选择,并且一切都在全局范围内,那么您可以不求助于 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>
警告:正如此处其他人所述,此问题是基于不灵活的客户要求。虽然这个问题是有效的,但如果可能的话,您绝对应该使用更简单的解决方案(例如:将您的设置放在一个对象中)!
我有一个变量数组,我想成为 "watching out" 的变量。也就是说:如果它们之前在代码中定义过,我需要能够对它们的值进行操作。
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,最好的做法是什么?
这类问题的答案几乎都是"You're thinking about the problem wrong.",这里也是如此。
你假设这应该用变量来完成,这让你陷入了只能使用 eval()
走出那个角落的困境。我知道客户可能要求提供常规变量,但如果我是一名房屋建筑商并且客户要求我用棉花糖建造房屋,我会说 "no",这不是这样做的方法。
解决方案是从一开始就使用带有键和值的对象,这样您以后就可以使用数组索引语法,而不是 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);
假设您别无选择,并且一切都在全局范围内,那么您可以不求助于 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>