繁体   English   中英

在括号表示法中嵌套点表示法以创建嵌套对象

[英]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.

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