Javascript对象:获取父级

Dän*_*änu 123 javascript

我有以下(嵌套)对象:

obj: { subObj: { foo: 'hello world' } };
Run Code Online (Sandbox Code Playgroud)

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

var s = obj.subObj;
Run Code Online (Sandbox Code Playgroud)

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

var o = s.parent;
Run Code Online (Sandbox Code Playgroud)

这有点可能吗?

Mik*_*Mik 105

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

看看这个:

var main = {
    name : "main object",
    child : {
        name : "child object"
    }
};
Run Code Online (Sandbox Code Playgroud)

如果你问主要对象它的子名是什么(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();
Run Code Online (Sandbox Code Playgroud)

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

如果你main.child.parent.name现在试着去,你会做对的.
这有点棘手,但它工作正常.

  • 这应该是公认的答案. (5认同)
  • 在使用大型父项时,这是否会产生任何性能问题,还是仅仅创建对单个对象的第二个引用? (2认同)
  • @Josiah:性能问题不大。它只是创建对父对象的第二个引用。 (2认同)

Mat*_*hen 75

没有.无法知道它来自哪个物体.

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

你也可以这样做:

var obj = { subObj: {foo: 'hello world'} };
var obj2 = {};
obj2.subObj = obj.subObj;
var s = obj.subObj;
Run Code Online (Sandbox Code Playgroud)

您现在有三个引用,, obj.subObjobj2.subObj,和s同一个对象.它们都不是特别的.


小智 46

这是一个老问题但是当我遇到它寻找答案时,我想我会在他们遇到同样的问题时加上我的答案来帮助其他人.

我有这样的结构:

var structure = {
    "root":{
        "name":"Main Level",
        nodes:{
            "node1":{
                "name":"Node 1"  
            },
            "node2":{
                "name":"Node 2"  
            },
            "node3":{
                "name":"Node 3"  
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

目前,通过引用其中一个子节点,我不知道如何使用它的名称值"Main Level"获取父节点.

现在我介绍一个遍历结构的递归函数,并为每个节点对象添加一个父属性,并将其填充为其父节点.

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

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

setParent(structure.root);
Run Code Online (Sandbox Code Playgroud)

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

var node2 = structure.root.nodes["node2"];
console.log(node2.parent.name);
Run Code Online (Sandbox Code Playgroud)

它将输出"主要级别".

希望这可以帮助..

  • @Nonlinearsound当对象很大且具有许多嵌套级别时,性能如何? (2认同)

Ste*_*ich 16

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

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

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

当嵌套对象增长/变化时,你如何维护父母?

如果我添加一个新的子子对象,它如何填充其父属性?如果你(1)使用了一个init函数,那么初始化已经完成了,所以你必须(2)通过一个函数传递对象来搜索新的子元素并添加适当的父元素.

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

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

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

    var p = new Proxy({parent: target}, parenter);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 复制提供的对象属性 - 因为您在此循环中设置代理属性,所以parenter处理程序正在递归地工作; 嵌套对象在每个级别都被赋予父级

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

    return target[prop] = p;
    
    Run Code Online (Sandbox Code Playgroud)

完整代码

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"
Run Code Online (Sandbox Code Playgroud)

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

  • 伟大的!就我而言,这段代码有问题,因为我的项目使用“use strict”。为了解决这个问题,我只需在“set”函数的末尾添加“return true” (3认同)

luk*_*asz 8

有一个更"顺畅"的解决方案:)

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;
Run Code Online (Sandbox Code Playgroud)


Poi*_*ess 6

为了进一步迭代Mik的答案,您还可以递归地将父级附加到所有嵌套对象.

var myApp = {

    init: function() {
        for (var i in this) {
            if (typeof this[i] == 'object') {
                    this[i].init = this.init;
                    this[i].init();
                    this[i].parent = this;
            }
        }
        return this;
    },

    obj1: {
        obj2: {
            notify: function() {
                console.log(this.parent.parent.obj3.msg);
            }
        }
    },

    obj3: {
        msg: 'Hello'
    }

}.init();

myApp.obj1.obj2.notify();
Run Code Online (Sandbox Code Playgroud)

http://jsbin.com/zupepelaciya/1/watch?js,console