2010-06-05 135 views
91

我有以下的(嵌套)对象:JavaScript对象:获得父

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

我做的下一件事是引用这样子对象:

var s = obj.subObj; 

现在我想做些什么是从变量s中获取对象obj的引用。 类似于:

var o = s.parent; 

这是不是有可能?

+7

JavaScript有很好的文档记录, [ECMAScript规范](http://www.ecma-international.org/publications/standards/Ecma-262.htm)或阅读一本书,如* JavaScript。 David Flanagan的权威指南*顺便说一句,没有这样的东西作为JSON对象:JSON只是JavaScript对象的符号。 – 2010-06-05 14:45:20

+0

感谢您的链接。对不起,JSON,我只是把这一个,因为我正在研究一个JSON相关的片段 - 我认为它可能是最有用的(JSON)来获取父对象。 – 2010-06-05 14:59:28

+0

'obj.subObj'只是对象的引用。如果有可能得到对象的“父”,那将是一团糟,因为可能有多个指向同一对象的指针,它将返回多个父对象。 – 2014-07-06 22:43:13

回答

60

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

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

你也可以这样做:

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

你现在有三个参考,obj.subObjobj2.subObjs,同一个对象。它们都不是特别的。

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

嵌套对象(子)(父母)无法直接从其父母获取数据。

对此一看:

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
因此,我们直接在child对象内定义parent属性。
然后(可选)我们可以删除init方法。
最后,我们将主要对象返回为init函数的输出。

如果您现在尝试获得main.child.parent.name,那么您将得到正确的结果。
这是有点棘手,但它工作正常。

+1

这是否会在处理大型父项时创建任何性能问题,还是仅创建对单个对象的第二个引用? – Josiah 2015-07-03 15:19:26

+0

@Josiah:没有太多的性能问题。它只是创建对父对象的第二个引用。 – 2017-06-01 08:58:25

+0

这应该是被接受的答案。 – 2017-09-22 15:38:29

39

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

我有这样的结构:

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

目前,通过参考子节点,我不知道如何让父节点与它的名字值“主级”之一。

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

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

如果我现在有一个引用根的秒子节点,我可以调用。

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

它会输出“Main Level”。

希望这有助于..

+0

不错,谢谢。 – 2013-07-30 09:44:46

+1

这对我很有帮助!即使JavaScript本身不提供“父”属性,我们也可以根据需要手动添加。 – 2014-04-12 01:35:05

+0

@Nonlinearsound当对象很大且嵌套层次很多时,性能如何? – 2015-08-25 06:19:49

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

要在Mik的的回答进一步的迭代,你也可以recursivey家长重视所有嵌套对象。

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

2

你可以试试这个(这使用一个构造函数,但我敢肯定,你可以改变它张望了一下):

function Obj() { 
    this.subObj = { 
     // code 
    } 
    this.subObj.parent = this; 
} 
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(); 
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; 
     } 
    } 

,那么你可以通过使用访问某些对象的父对象的somechildarray .parent

1

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

考虑 -

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

变量OBJ现在这个样子 -

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

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

实施例 -

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 

当然,在不知道或具有到最外面的对象的引用,也没有办法来做到这一点。这不是一个实际的也不是一个有效的解决方案。我将继续努力解决这个问题,希望能为这个问题找到一个好的答案。

12

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

  1. 通过在嵌套对象被创建时使用的init功能循环,或...
  2. 供应嵌套对象来填充功能出parent属性

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

你如何保持父母嵌套对象的增长/改变?

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

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

下面的方法是创建一个处理程序的代理每一个对象被设置时总是添加parent属性。我已经将这个处理程序称为parenter处理程序。 parenter的责任是识别何时设置对象,然后...

  1. 创建具有相应parent伪代理和parenter处理

    var p = new Proxy({parent: target}, parenter); 
    
  2. 复制在提供对象properties-- 因为你在这个循环中的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" 

请注意,所有根儿童总是有父母的属性,甚至稍后添加的孩子。