当节点/属性名称为变量/参数时,寻找eval()替代项

时间:2019-03-05 19:43:51

标签: javascript eval

很明显,当脚本中存在/定义了属性(例如 id )时,我们应该使用obj[id]而不是{{1 }}。但是,对于属性名称本身是变量且未定义的情况,例如在接收为参数时,我还没有找到解决方案。在我的情况下,服务器上有node.js,它从客户端通过socket.io发送一个JSON对象 requestData requestData 包含一个键/值对: requestData.key 是组成节点名称的数组元素的JSON路径,而 requestData.val 是要存储在该元素中的值。

在服务器脚本中,有一个定义的JSON对象,名为 root ,其中包含与应用程序相关的信息,例如:

eval('obj.' + id)

如果客户端要发送更新元素的请求-例如,更改 root.pages.TM1010.componentName 的值,这将是这样从客户端发送:

"root": {
  "pages": {
    "TM1010": {
      "appId": "TM1010",
      "componentName": "UserTasksPage"
    },
    "TM1020": {
      "appId": "TM1020",
      "componentName": "UsersPage"
    }
  }
}

这是在服务器上接收和执行的方式:

let requestData = {'key': ['pages', 'TM1010', 'componentName'], 'val': newComponentName};
this.socket.emit('changeData', requestData);

这样最后执行的内容( str 的值)是:

socket.on('changeData', (requestData) => {
  var str = 'root'
  var key = requestData.key
  var len = key.length;
  for (var i = 0; i < len; i++) {
   str = str + '["' + key[i] + '"]'
  }
  str = str + '=requestData.val'
  eval(str)
});

如果没有root["pages"]["TM1010"]["componentName"]=requestData.val 怎么办?

正如我提到的,我不知道将从客户端发送的那些元素的名称。我在服务器上仅拥有一个名为“ root”的JSON对象,我想在从客户端接收数据时不断对其进行添加/更新。 我已经尝试过基于JEXL或mathjs的解决方案,但似乎不适用于这种情况。

1 个答案:

答案 0 :(得分:1)

您可以通过获取对象来减少键,并为最后一个键分配值。

const
    setValue = (object, keys, value) => {
        var path = keys.slice(),
            last = path.pop();
        path.reduce((o, k) => o[k], object)[last] = value;
    };

var data = { root: { pages: { TM1010: { appId: "TM1010", componentName: "UserTasksPage" }, TM1020: { appId: "TM1020", componentName: "UsersPage" } } } },
    requestData = { key: ['pages', 'TM1010', 'componentName'], val: 'newComponentName' };

setValue(data.root, requestData.key, requestData.val);

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }