Javascript 对象:获取父对象

IT技术 javascript
2021-01-13 18:42:37

我有以下(嵌套)对象:

obj: { subObj: { foo: 'hello world' } };

接下来我要做的是像这样引用子对象:

var s = obj.subObj;

现在我想做的是obj从变量中获取对对象的引用s就像是:

var o = s.parent;

这有可能吗?

6个回答

另一个对象(父对象)内的嵌套对象(子对象)无法直接从其父对象获取数据。

看看这个:

var main = {
    name : "main object",
    child : {
        name : "child object"
    }
};

如果你问主对象它的子名称是什么 ( main.child.name) 你会得到它。
相反,您不能反之亦然,因为孩子不知道其父母是谁。
(你可以得到,main.name但你不会得到main.child.parent.name)。

顺便说一下,一个函数可能有助于解决这个线索。
让我们扩展上面的代码:

var main = {
    name : "main object",
    child : {
        name : "child object"
    },
    init : function() {
        this.child.parent = this;
        delete this.init;
        return this;
    }
}.init();

init函数内部,您只需调用this.
所以我们parent直接在child对象内部定义属性
然后(可选)我们可以删除该init方法。
最后,我们将主对象作为init函数的输出返回

如果你main.child.parent.name现在就努力,你就会得到它。
这有点棘手,但效果很好。

这在与大父对象一起工作时是否会产生任何性能问题,或者只是创建对单个对象的第二个引用?
2021-03-11 18:42:37
这很聪明,正是我所需要的。
2021-03-11 18:42:37
这应该是公认的答案。
2021-04-01 18:42:37
当深度克隆并破坏应用程序时,它将无限下降。main.child.parent.child.parent.child.parent.child.parent.child.parent...
2021-04-03 18:42:37
@Josiah:性能问题不大。它只是创建对父对象的第二个引用。
2021-04-05 18:42:37

不。没有办法知道它来自哪个对象。

s并且obj.subObj两者都只是对同一个对象的引用。

你也可以这样做:

var obj = { subObj: {foo: 'hello world'} };
var obj2 = {};
obj2.subObj = obj.subObj;
var s = obj.subObj;

您现在拥有对同一对象的三个引用、obj.subObjobj2.subObjs它们都不是特别的。

这是一个老问题,但当我遇到它寻找答案时,我想我会添加我的答案以帮助其他人,一旦他们遇到同样的问题。

我有这样的结构:

var structure = {
    "root":{
        "name":"Main Level",
        nodes:{
            "node1":{
                "name":"Node 1"  
            },
            "node2":{
                "name":"Node 2"  
            },
            "node3":{
                "name":"Node 3"  
            }
        }
    }
}

目前,通过引用子节点之一,我不知道如何获取名称值为“Main Level”的父节点。

现在我介绍一个递归函数,它遍历结构并向每个节点对象添加一个父属性,并像这样用它的父对象填充它。

var setParent = function(o){
     if(o.nodes != undefined){
          for(n in o.nodes){
              o.nodes[n].parent = o;
              setParent(o.nodes[n]);
          }
     }
}

然后我只需调用该函数,现在就可以获取此对象树中当前节点的父节点。

setParent(structure.root);

如果我现在有对 root 的 seconds 子节点的引用,我可以调用。

var node2 = structure.root.nodes["node2"];
console.log(node2.parent.name);

它将输出“主级别”。

希望这可以帮助..

我更喜欢这个,因为我不需要为所有孩子写一些东西:-)
2021-03-12 18:42:37
这对我帮助很大!即使 JavaScript 本身不提供“父”属性,我们也可以根据需要手动添加一个。
2021-03-27 18:42:37
@MSC 并不奇怪。对于不使用或不想要的大型对象来说,这将是荒谬的开销,就像 Sajid 所问的那样。
2021-03-28 18:42:37
是的,我也这样做了。奇怪的是 JS 没有内置这个。
2021-04-06 18:42:37
@Nonlinearsound 当对象很大且嵌套层次多时,性能如何?
2021-04-09 18:42:37

这里的许多答案都涉及循环遍历一个对象并“手动”(尽管以编程方式)创建一个存储对父级的引用的父级属性。实现这一点的两种方法似乎是......

  1. init在创建嵌套对象时使用函数循环,或者...
  2. 将嵌套对象提供给填充父属性的函数

两种方法都有相同的问题......

随着嵌套对象的增长/变化,您如何维护父母?

如果我添加一个新的子子对象,它如何填充其父属性?如果您 (1) 使用init函数,则初始化已经完成,因此您必须 (2) 通过函数传递对象以搜索新子项并添加适当的父属性。

使用 ES6 代理添加parent对象/子对象set

下面的方法是为代理创建一个处理程序,每次设置对象时总是添加一个父属性。我称这个处理程序为parenter处理程序。parenter职责是当被设定一个对象,然后以承认...

  1. 使用适当的parentparenter处理程序创建一个虚拟代理

    var p = new Proxy({parent: target}, parenter);
    
  2. 复制提供的对象属性——因为你在这个循环中设置代理属性,parenter处理程序递归地工作;嵌套对象在每个级别都有父级

    for(key in value){
        p[key] = value[key];
      }
    
  3. 设置代理而不是提供的对象

    return target[prop] = p;
    

完整代码

var parenter = {
  set: function(target, prop, value){
    if(typeof value === "object"){
      var p = new Proxy({parent: target}, parenter);
      for(key in value){
        p[key] = value[key];
      }
      return target[prop] = p;
    }else{
      target[prop] = value;
    }
  }
}

var root = new Proxy({}, parenter);

// some examples
root.child1 = {
    color: "red", 
    value: 10, 
    otherObj: { 
       otherColor: "blue", 
       otherValue: 20
    }
}

// parents exist/behave as expected
console.log(root.child1.color)                 // "red"
console.log(root.child1.otherObj.parent.color) // "red"

// new children automatically have correct parent
root.child2 = {color: "green", value3: 50};
console.log(root.child2.parent.child1.color)   // "red"

// changes are detected throughout
root.child1.color = "yellow"
console.log(root.child2.parent.child1.color)   // "yellow"

请注意,所有根子项始终具有父属性,即使是稍后添加的子项。

伟大的!就我而言,此代码有问题,因为我的项目使用“严格使用”。要修复它,我只需在“set”函数的末尾添加“return true”
2021-03-31 18:42:37

对此有一个更“平滑”的解决方案:)

var Foo = function(){
  this.par = 3;

  this.sub = new(function(t){ //using virtual function to create sub object and pass parent object via 't'
    this.p = t;
    this.subFunction = function(){
      alert(this.p.par);
    }
  })(this);
}

var myObj = new Foo();
myObj.sub.subFunction() // will popup 3;

myObj.par = 5;
myObj.sub.subFunction() // will popup 5;