Javascript 对象: 获取父对象

我有以下(嵌套的)对象:

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

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

var s = obj.subObj;

现在我要做的是从变量 s中获取对对象 obj的引用。 比如:

var o = s.parent;

这有可能吗?

305703 次浏览

不,没办法知道它来自哪个物体。

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

你也可以这样做:

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

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

试试这个,直到出现一个非否定答案:

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

还有一个更“平滑”的解决方案:)

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;

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

看看这个:

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”的父节点。

现在我介绍一个递归函数,它遍历结构并向每个节点对象添加一个父属性,然后用它的父属性填充它,如下所示。

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 的秒子节点的引用,我可以直接调用。

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

它将输出“主要水平”。

希望这个能帮上忙。

只是在子属性中保留父值

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

要进一步迭代 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

您可以尝试这样做(它使用了一个构造函数,但是我确信您可以稍微修改一下它) :

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

您将需要子元素来存储父元素这个变量。因为 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();

当我加载一个 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;
}
}

然后您可以通过使用. rent 访问 some echildarray 中某个对象的父对象

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

考虑一下

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

当然,如果不知道或没有对最外层对象的引用,就没有办法做到这一点。这既不实际,也不是一个有效的解决方案。我将继续这方面的工作,并希望找到一个良好的答案,这个问题。

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

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

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

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

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

每当对象/子对象为 set时,使用 ES6代理添加 parent

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

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

    var p = new Proxy({parent: target}, parenter);
    
  2. Copy in the supplied objects properties-- Because you're setting the proxy properties in this loop the parenter handler is working recursively; nested objects are given parents at each level

    for(key in value){
    p[key] = value[key];
    }
    
  3. Set the proxy not the supplied object

    return target[prop] = p;
    

Full code

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"

请注意,所有根子级始终具有父属性,即使子级是以后添加的。