简体   繁体   English

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

[英]Nesting dot notation within bracket notation to create nested objects

From Eloquent JavaScript: "Write a function arrayToList that builds up a list structure like"来自 Eloquent JavaScript:“编写一个 function arrayToList 来构建类似的列表结构”

let LL = { data: 1, next: { data: 2, next: { data: 3, next: null }}};让LL = {数据:1,下一个:{数据:2,下一个:{数据:3,下一个:null}}};

I understand the typical solution to this problem, where the list must be built from the inside out:我了解此问题的典型解决方案,其中列表必须从内到外构建:

function arrToLList(arr) {
  let LList = null;
  for (let i = arr.length - 1; i >= 0; i--) {
    LList = { data: arr[i], next: LList };
  }
  return LList;
}

But my initial solution was to brute force it with a typical for loop.但我最初的解决方案是使用典型的 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;
}

You may have noticed this doesn't work because we can't mix dot notation and bracket notation.您可能已经注意到这不起作用,因为我们不能混合点表示法和括号表示法。 I rather enjoyed almost figuring this one out for myself but I can't make the idea work and I'm not sure if it's even possible.我几乎很喜欢为自己解决这个问题,但我无法让这个想法奏效,我不确定它是否可能。 Is there something I'm missing about creating nested JS objects?关于创建嵌套的 JS 对象,我有什么遗漏吗?

As you are trying to access an objects parameters using strings.当您尝试使用字符串访问对象参数时。 You can't use dot notation with string.您不能对字符串使用点表示法。 eg例如

let data = {name:'test'};
console.log("data.name");

this is what you're attempting and it will return data.name and not the value test .这就是您正在尝试的,它将返回data.name而不是值test

you can do the following though: data['name'] so with nested object you can do the following:您可以执行以下操作: data['name']因此使用嵌套的 object 您可以执行以下操作:

LList['next']['next']...['next']['data']

to get the n'th data element.获取第 n 个数据元素。

What you want to achieve is possible, but you need to customize the functionality of how getting a property works when you use bracket notation.您想要实现的目标是可能的,但是当您使用括号表示法时,您需要自定义获取属性的功能。 As you mentioned, using dot notation with bracket notation won't work, you need a way to define this logic yourself.正如您所提到的,将点符号与括号符号一起使用是行不通的,您需要一种自己定义此逻辑的方法。 ES6 introduced Proxies which allows you to specify a set method trap for your object. ES6 引入了代理,它允许你为你的 object 指定一个设置方法陷阱。 Whenever you set a value on the object, the set method will be called.每当您在 object 上设置值时,都会调用 set 方法。 Using this idea, you can split the dot-notation string by .使用这个想法,您可以将点符号字符串拆分为. and traverse the path it returns to get your nested object.并遍历它返回的路径以获取嵌套的 object。 Once you have retrieved the nested object, you can set its value.检索到嵌套的 object 后,您可以设置其值。

See example below:请参见下面的示例:

 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]));

However, you don't need to use a proxy.但是,您不需要使用代理。 A more straightforward way of doing this would be by creating a method such as setValueByPath(val, obj, strPath) which performs the logic in the proxy for you.一种更直接的方法是创建一个方法,例如setValueByPath(val, obj, strPath) ,它为您执行代理中的逻辑。 Then, instead of setting your object using bracket notation, you simply call the setValueByPath(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