繁体   English   中英

通过字符串值引用JavaScript对象-无需使用eval()

[英]Refer to a javascript object by string value - without using eval()

环顾四周,没有发现任何似乎与我尝试做的事情匹配的事情。

我想通过一个字符串表示引用一个对象,虽然我到处看看我看到使用eval()是坏的-虽然不能找到一个方法来做到这一点,而不使用eval()

所以我的用例:

我在按钮上有一个data属性;

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对象。

像这样:

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

我想到了几种解决方案。 @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;

前提是您可以确保不能以任何方式修改该属性,否则可能会对正在实施该属性的站点/项目造成损害,因此我看不到任何问题。

我不确定这是否适合您的情况,但是避免评估的一个简单解决方案可能是添加“ 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更快,更安全。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM