Javascript对象:得到父母
我有以下(嵌套)的对象:
obj: { subObj: { foo: 'hello world' } };
接下来我要做的就是像这样引用子对象:
var s = obj.subObj;
现在我想要做的是从variabless
获取对象obj
的引用。 就像是:
var o = s.parent;
这有可能吗?
不,不知道它来自哪个对象。
s
和obj.subObj
都只是对同一个对象的引用。
你也可以这样做:
var obj = { subObj: {foo: 'hello world'} }; var obj2 = {}; obj2.subObj = obj.subObj; var s = obj.subObj;
您现在有三个引用, obj.subObj
, obj2.subObj
和s
,对同一个对象。 没有一个是特别的。
另一个对象(父对象)中的嵌套对象(子对象)不能直接从其父对象中获取数据。
看看这个:
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
那么您将得到正确的结果。
这是有点棘手,但它工作正常。
这是一个古老的问题,但当我遇到它寻找一个答案,我想我会加我的答案,以帮助其他人,一旦他们得到同样的问题。
我有这样的结构:
var structure = { "root":{ "name":"Main Level", nodes:{ "node1":{ "name":"Node 1" }, "node2":{ "name":"Node 2" }, "node3":{ "name":"Node 3" } } } }
目前,通过引用其中一个子节点,我不知道如何获得名称为“Main Level”的父节点。
现在我介绍一个遍历结构的recursion函数,并为每个节点对象添加一个父属性,并像这样填充它的父项。
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”。
希望这可以帮助..
这里的许多答案都涉及遍历对象和“手动”(尽pipe以编程方式)创build一个存储对父对象的引用的父属性。 实施这两种方法似乎是…
- 使用
init
函数在创build嵌套对象时循环,或者… - 将嵌套对象提供给填充父属性的函数
两种方法都有同样的问题…
随着嵌套对象的增长/变化,你如何维护父母?
如果我添加一个新的子子对象,它是如何获得其父属性填充? 如果(1)使用init
函数,初始化已经完成,所以你必须(2)通过函数传递对象来search新的子项并添加适当的父属性。
只要设置了对象/子对象,就可以使用ES6 Proxy来添加parent
下面的方法是为代理创build一个处理程序,每次设置一个对象时总会添加一个父属性。 我已经把这个处理程序叫做parenter
处理程序。 承担责任是识别何时设置对象,然后…
-
用合适的
parent
和parent
处理程序创build一个虚拟代理var p = new Proxy({parent: target}, parenter);
-
在提供的对象属性中复制 – 因为你要在这个循环中设置代理属性,所以
parenter
处理器正在recursion地工作; 嵌套的对象被赋予每个级别的父母for(key in value){ p[key] = value[key]; }
-
设置代理不是提供的对象
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"
请注意,所有根子项都始终具有父项属性,甚至是稍后添加的子项。
有一个更平滑的解决scheme:)
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;
为了进一步迭代Mik的答案,你也可以recursion地将父项附加到所有的嵌套对象上。
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();
你可以尝试这个(这使用了一个构造函数,但是我相信你可以改变它):
function Obj() { this.subObj = { // code } this.subObj.parent = this; }
试试这个,直到出现一个非答案。
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);
您需要孩子将这个variables存储在父母身上。 由于Parent是唯一可以访问它的对象,所以它也需要一个函数把这个variables放到子variables中,像这样。
var Parent = { Child : { that : {}, }, init : function(){ this.Child.that = this; } }
为了testing这个,试着在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();
我一直在寻找一个解决scheme,为我自己的宠物项目find当前对象的父对象。 在当前对象中添加对父对象的引用会在两个对象之间创build循环关系。
考虑 –
var obj = { innerObj: {}, setParent: function(){ this.innerObj.parent = this; } }; obj.setParent();
variablesobj现在看起来像这样 –
obj.innerObj.parent.innerObj.parent.innerObj …
不是很好。 目前为止唯一的解决scheme是创build一个迭代最外层对象的所有属性的函数,直到find当前对象的匹配,然后返回该对象。
示例 –
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
当然,如果不知道或没有参考最外层的对象,就没有办法做到这一点。 这不是一个实际的也不是一个有效的解决scheme。 我将继续努力解决这个问题,希望能find一个很好的答案。
只是保持父属性值的子属性
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);
当我加载一个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中某个对象的父对象