[英]Nesting dot notation within bracket notation to create nested objects
来自 Eloquent JavaScript:“编写一个 function arrayToList 来构建类似的列表结构”
让LL = {数据:1,下一个:{数据:2,下一个:{数据:3,下一个:null}}};
我了解此问题的典型解决方案,其中列表必须从内到外构建:
function arrToLList(arr) {
let LList = null;
for (let i = arr.length - 1; i >= 0; i--) {
LList = { data: arr[i], next: LList };
}
return LList;
}
但我最初的解决方案是使用典型的 for 循环强制它。
function arrayToLList(arr) {
let d = "data";
let n = "next";
let LList = nextNode();
for (let i = 0; i < arr.length; i++) {
LList[d] = arr[i];
d = "next." + d;
LList[n] = nextNode();
n = "next." + n;
}
function nextNode() {
return {
data: null,
next: null
};
}
return LList;
}
您可能已经注意到这不起作用,因为我们不能混合点表示法和括号表示法。 我几乎很喜欢为自己解决这个问题,但我无法让这个想法奏效,我不确定它是否可能。 关于创建嵌套的 JS 对象,我有什么遗漏吗?
当您尝试使用字符串访问对象参数时。 您不能对字符串使用点表示法。 例如
let data = {name:'test'};
console.log("data.name");
这就是您正在尝试的,它将返回data.name
而不是值test
。
您可以执行以下操作: data['name']
因此使用嵌套的 object 您可以执行以下操作:
LList['next']['next']...['next']['data']
获取第 n 个数据元素。
您想要实现的目标是可能的,但是当您使用括号表示法时,您需要自定义获取属性的功能。 正如您所提到的,将点符号与括号符号一起使用是行不通的,您需要一种自己定义此逻辑的方法。 ES6 引入了代理,它允许你为你的 object 指定一个设置方法陷阱。 每当您在 object 上设置值时,都会调用 set 方法。 使用这个想法,您可以将点符号字符串拆分为.
并遍历它返回的路径以获取嵌套的 object。 检索到嵌套的 object 后,您可以设置其值。
请参见下面的示例:
function arrayToLList(arr) { let d = "data"; let n = "next"; let LList = nextNode(); for (let i = 0; i < arr.length; i++) { LList[d] = arr[i]; d = "next." + d; if(i < arr.length-1) // don't add null object to last node LList[n] = nextNode(); n = "next." + n; } function nextNode() { const obj = { data: null, next: null }; return new Proxy(obj, { set: function(obj, key, val) { const path = key.split('.'); const last = path.pop(); for(const prop of path) obj = obj[prop]; obj[last] = val; return true; } }); } return LList; } console.log(arrayToLList([1, 2, 3]));
但是,您不需要使用代理。 一种更直接的方法是创建一个方法,例如setValueByPath(val, obj, strPath)
,它为您执行代理中的逻辑。 然后,无需使用括号符号设置 object,您只需调用setValueByPath(obj, strPath)
:
function setValudByPath(val, obj, strPath) { // pefroms same logic from proxy, just using reduce instead const path = strPath.split('.'); const last = path.pop(); path.reduce((nested, p) => nested[p], obj)[last] = val; } function arrayToLList(arr) { let d = "data"; let n = "next"; let LList = {data: null, next: null}; for (let i = 0; i < arr.length; i++) { setValudByPath(arr[i], LList, d); // same as LList[d] = arr[i]; d = "next." + d; if(i < arr.length-1) // don't add null object to last node setValudByPath({data: null, next: null}, LList, n); // same as: LList[n] = nextNode(); n = "next." + n; } return LList; } console.log(arrayToLList([1, 2, 3]));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.