环顾四周,没有找到任何与我想做的事情相符的事情。
我试图通过字符串表示来引用一个对象,虽然我看到的每个地方都看到使用eval()
很糟糕 - 虽然在没有使用eval()
的情况下无法找到方法
所以我的用例:
我在按钮上有数据属性;
data-original-data-object="window.app.myData.originalData"
单击该按钮时,我需要访问window.app.myData.originalData
现在,我知道我能做到:
var dataObj = eval($(this).data('original-data-object'));
虽然还有其他办法吗?
如果有帮助,window.app.myData.originalData
存储的数据就是JSON对象。
答案 0 :(得分:3)
像这样:
var obj = (function(str){
var arr = str.split('.');
if (arr[0] === 'window'){
arr.shift();
}
return arr.reduce(function(a, b){
return a[b];
}, window);
}("window.app.myData.originalData"))
答案 1 :(得分:1)
我想到了几个解决方案。第一个解决方案在@CD答案中暗示。第二种是通过正则表达式将该字符串限制为只是属性名称,这样您就可以安全地使用eval。
遍历window
对象以获取值(无eval)
function getValue(s) {
var keys = s.split("."), o = window, key, i, length, undef;
if (keys[0] === "window") {
keys.shift();
}
for (i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (!(key in o) || o[key] === null || o[key] === undef) {
throw new Error("Could not get value of " + s);
}
o = o[key];
}
return o;
}
将字符串限制为有效的属性名称:
function getValue(s) {
var regex = /^[\w$][\w.]+$/, value;
if (regex.test(s)) {
try {
value = eval(s);
}
catch (error) {
throw new Error("Could not get value of " + s + " (" + error.message + ")");
}
}
else {
throw new Error("Could not get value of " + s);
}
return value;
}
使用:
var x = getValue(this.getAttribute("data-original-data-object"));
您希望避免使用eval,因为它可以随意执行您可能或可能无法控制的JavaScript。在这种特殊情况下,您知道所需的确切字符串类型。在我看来,我使用正则表达式来确保字符串只包含由点分隔的属性名称。说到安全性,这两行代码没有区别:
var x = eval("window.foo");
var x = window.foo;
答案 2 :(得分:0)
如果您可以确保无论如何都不能修改属性,这可能会对正在实施的网站/项目造成损害,我认为没有任何问题。
答案 3 :(得分:0)
我不确定这是否适用于您的情况,但是避免使用eval的简单解决方案可能是添加“window.app.myData.originalData”及其JSON数据作为将保留的对象的属性范围。
类似的东西:
var exampleData = { id:1, content:"..." };
var dataStore = { "window.app.myData.originalData": exampleData };
然后,在您的点击处理程序中:
var retrievedData = dataStore[$(this).data('original-data-object')]; // uses "window.app.myData.originalData" to retrieve exampleData
在这种情况下,您需要使用括号表示法访问数据,因为。属性名称中的字符。但是,这种方法应该比尝试使用eval更快更安全。