当 node/attribute 名称为 variable/parameter 时寻找 eval() 替代方案
Looking for eval() alternative when node/attribute name is variable/parameter
很明显,当在脚本中定义属性(例如id)exists/is时,我们应该使用obj[id]
而不是 eval('obj.' + id)
。但是,对于属性名称本身是变量且未定义的情况,我还没有找到解决方案 - 例如当作为参数接收时。在我的例子中,我在服务器上有 node.js 接收一个 JSON 对象 requestData 从客户端通过 socket.io。 requestData 包含一个 key/value 对:requestData.key 是构成元素 JSON 路径的节点名称数组,requestData.val 是要存储在该元素中的值。
在服务器脚本中有一个名为 root 的已定义 JSON 对象,其中包含与应用程序相关的信息,用于示例:
"root": {
"pages": {
"TM1010": {
"appId": "TM1010",
"componentName": "UserTasksPage"
},
"TM1020": {
"appId": "TM1020",
"componentName": "UsersPage"
}
}
}
如果客户端要发送更新元素的请求 - 例如更改 root.pages.TM1010.componentName[=50= 的值] - 这是从客户端发送的方式:
let requestData = {'key': ['pages', 'TM1010', 'componentName'], 'val': newComponentName};
this.socket.emit('changeData', requestData);
这是它在服务器上接收和执行的方式:
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)
});
所以最后正在执行的(str的值)是:
root["pages"]["TM1010"]["componentName"]=requestData.val
如果没有 eval()
怎么办?
如前所述,我不知道将从客户端发送的那些元素的名称。我在服务器上只有一个名为 'root' 的 JSON 对象,当我从客户端接收数据时,我想连续 add/update 到它。
我尝试过基于 JEXL 或 mathjs 的解决方案,但它似乎不适用于此类情况。
您可以通过获取对象并使用最后一个键分配值来减少键。
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; }
很明显,当在脚本中定义属性(例如id)exists/is时,我们应该使用obj[id]
而不是 eval('obj.' + id)
。但是,对于属性名称本身是变量且未定义的情况,我还没有找到解决方案 - 例如当作为参数接收时。在我的例子中,我在服务器上有 node.js 接收一个 JSON 对象 requestData 从客户端通过 socket.io。 requestData 包含一个 key/value 对:requestData.key 是构成元素 JSON 路径的节点名称数组,requestData.val 是要存储在该元素中的值。
在服务器脚本中有一个名为 root 的已定义 JSON 对象,其中包含与应用程序相关的信息,用于示例:
"root": {
"pages": {
"TM1010": {
"appId": "TM1010",
"componentName": "UserTasksPage"
},
"TM1020": {
"appId": "TM1020",
"componentName": "UsersPage"
}
}
}
如果客户端要发送更新元素的请求 - 例如更改 root.pages.TM1010.componentName[=50= 的值] - 这是从客户端发送的方式:
let requestData = {'key': ['pages', 'TM1010', 'componentName'], 'val': newComponentName};
this.socket.emit('changeData', requestData);
这是它在服务器上接收和执行的方式:
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)
});
所以最后正在执行的(str的值)是:
root["pages"]["TM1010"]["componentName"]=requestData.val
如果没有 eval()
怎么办?
如前所述,我不知道将从客户端发送的那些元素的名称。我在服务器上只有一个名为 'root' 的 JSON 对象,当我从客户端接收数据时,我想连续 add/update 到它。 我尝试过基于 JEXL 或 mathjs 的解决方案,但它似乎不适用于此类情况。
您可以通过获取对象并使用最后一个键分配值来减少键。
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; }