2010-06-05 134 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" 

請注意,所有根兒童總是有父母的屬性,甚至稍後添加的孩子。