Javascript对象:获取父级

时间:2010-06-05 14:37:26

标签: javascript

我有以下(嵌套)对象:

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

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

var s = obj.subObj;

现在我想做的是从变量obj中获取对象s的引用。 类似的东西:

var o = s.parent;

这有可能吗?

12 个答案:

答案 0 :(得分:99)

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

看看这个:

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,那么你就会做对 这有点棘手,但工作正常。

答案 1 :(得分:74)

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

sobj.subObj都只是引用同一个对象。

你也可以这样做:

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

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

答案 2 :(得分:44)

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

我有这样的结构:

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

并输出“Main Level”。

希望这会有所帮助..

答案 3 :(得分:13)

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

  1. 在创建嵌套对象时使用init函数循环,或者......
  2. 将嵌套对象提供给填充父属性的函数
  3. 两种方法都有同样的问题......

    当嵌套对象增长/更改时,如何维护父对象?

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

    只要对象/子对象为parent

    ,就使用ES6代理添加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;
      
    4. 完整代码

      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"
      

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

答案 4 :(得分: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;

答案 5 :(得分: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();

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

答案 6 :(得分:2)

尝试此操作,直至出现非拒绝答案:

function parent() {
  this.child;
  interestingProperty = "5";
  ...
}

function child() {
  this.parent;
  ...
}

a = new parent();
a.child = new child();
a.child.parent = a; // this gives the child a reference to its parent

alert(a.interestingProperty+" === "+a.child.parent.interestingProperty);

答案 7 :(得分:2)

你可以尝试这个(这使用了一个构造函数,但我相信你可以稍微改一下):

function Obj() {
    this.subObj = {
        // code
    }
    this.subObj.parent = this;
}

答案 8 :(得分:2)

我一直致力于为我自己的宠物项目找到当前对象的父对象的解决方案。在当前对象中添加对父对象的引用会在两个对象之间创建循环关系。

考虑 -

var obj = {
    innerObj: {},
    setParent: function(){
        this.innerObj.parent = this;
    }
};
obj.setParent();

变量obj现在看起来像这样 -

... obj.innerObj.parent.innerObj.parent.innerObj

这不好。到目前为止,我找到的唯一解决方案是创建一个函数,该函数迭代最外层Object的所有属性,直到找到当前Object的匹配,然后返回该Object。

示例 -

var obj = {
    innerObj: {
        innerInnerObj: {}
    }
};

var o = obj.innerObj.innerInnerObj,
    found = false;

var getParent = function (currObj, parObj) {
    for(var x in parObj){
        if(parObj.hasOwnProperty(x)){
            if(parObj[x] === currObj){
                found = parObj;
            }else if(typeof parObj[x] === 'object'){
                getParent(currObj, parObj[x]);
            }
        }
    }
    return found;
};

var res = getParent(o, obj); // res = obj.innerObj

当然,如果不知道或没有引用最外层的对象,就无法做到这一点。这不实用,也不是一种有效的解决方案。我将继续研究这个问题,希望能找到解决这个问题的好方法。

答案 9 :(得分:1)

您需要孩子将父变量存储起来。由于Parent是唯一可以访问它的对象,因此它还需要一个函数将该变量放入子变量中,就像这样。

var Parent = {
  Child : {
    that : {},
  },
  init : function(){
    this.Child.that = this;
  }
}

为了测试这一点,尝试在Firefox的Scratchpad中运行它,它对我有用。

var Parent = {
  data : "Parent Data",

  Child : {
    that : {},
    data : "Child Data",
    display : function(){
      console.log(this.data);
      console.log(this.that.data);
    }
  },
  init : function(){
    this.Child.that = this;
  }
}

Parent.init();
Parent.Child.display();

答案 10 :(得分:0)

仅保留父属性

中的父值
var Foo = function(){
    this.val= 4;
    this.test={};
    this.test.val=6;
    this.test.par=this;
}

var myObj = new Foo();
alert(myObj.val);
alert(myObj.test.val);
alert(myObj.test.par.val);

答案 11 :(得分:0)

当我加载一个json对象时,我通常通过迭代这样的对象数组来设置关系:

    for (var i = 0; i < some.json.objectarray.length; i++) {
        var p = some.json.objectarray[i];
        for (var j = 0; j < p.somechildarray.length; j++) {
            p.somechildarray[j].parent = p;
        }
    }

然后您可以使用.parent

访问somechildarray中某个对象的父对象