2012-11-23 228 views
4

我有例如像这样的对象:javascript获取父对象的嵌套?

obj = { 
    subobj1: { 

    }, 
    subobj2: { 
     func1: function(){ 

     }, 
     func2: function(){ 

     } 
    }, 
    subobj3: { 
     func3: function(){ 

     }, 
     func4: function(){ 

     }   
    }, 
} 

如何调用FUNC1从FUNC4内无需调用obj.subobj2.func1()?

回答

12

你不能。你不知道你的函数存在什么对象。

注意,这可能是在不止一个:你可以有你的现有代码后写成这样:

var obj2 = {some:obj.subobj3}; 

所以不可能有唯一的链接(也没有访问链接)从属性值持有它的对象。现在

,假设你会得到满意的对象创建了一个链接,你可以使用一个工厂来构建你的对象:

obj = (function(){ 
    var parent = { 
     subobj1: { 

     }, 
     subobj2: { 
      func1: function(){ 

      }, 
      func2: function(){ 

      } 
     }, 
     subobj3: { 
      func3: function(){ 

      }, 
      func4: function(){ 
       parent.subobj2.func1(); 
      }   
     } 
    }; 
    return parent; 
})(); 

然后就可以调用

obj.subobj3.func4(); 

Demonstration


编辑

我看到你给你的问题标签OOP。你应该知道我给出的模式更常用于定义模块。 JavaScript中的OOP更经常使用newprototype来完成,以便启用实例共享方法和继承。因为你可能需要模块而不是OOP,不过你似乎很好。

请参阅this introduction

+0

有功能如this.parent.func1()? – Joe

+1

你不能在对象声明中设置一个变量。这不工作 – sroes

+0

啊,有道理,从工厂外部调用subobj2.func1我必须调用obj.that.suboj2.func1? – Joe

0

这是不可能的。对象属性是通过它们设置的对象获取的。 JavaScript不会将根对象隐式设置为全局,因此您不能将obj.subobj2.func1别名为func1或以任何方式更短。如果您发现自己过度调用该函数,请尝试设置一个变量。

0

你不能直接这样做,因为没有办法象文件系统中的“..”那样“上”对象层次结构。

你可以做的是让变量直接指向子对象或子函数,这样你就不需要通过层次结构来调用它们。下面是用于创建的Javascript模块共同的图案:

obj = (function(){ 

    var obj1 = {...} 
    var obj2 = {...} 

    var func3 = function(){...}; 
    var func4 = function(){...}; 

    return { 
     subobj1: obj1, 
     subobj2: obj2, 
     subobj3: { 
      func3: func3, 
      func4: func4 
     } 
    } 
}()); 

在这个例子中,内部功能可以从他们的变量直接访问obj1obj2func3func4。自调用函数使得这些内部变量是私密的,并且从外部隐藏,并且返回语句允许您只导出要公开的函数。

0

这里是一个asnwer更ActionScript喜欢和容易理解:

function MainObject() { 
    this.x = 100; 
    this.y = 50; 
    this.second = new SecondObject(this); 
} 

function SecondObject(p) { 
    this.parent = p; 
} 

var firstobject = new MainObject(); 

// Saving a reference to SecondObject. 
var secondObject = firstobject.second; 

// Because of parent variable, you can access second object parent without needing to have the parent object in a variable. 
console.log(secondObject.parent.x); 
console.log(secondObject.parent.y); 

只要记住一个对象不能有多个父。

0

您的对象实现是不可能的。取决于你的需要 - 下面的实现可能是有用的:

obj = function(){ 
    var obj = { 
    subobj1: { 

    }, 
    subobj2: { 
     func1: function(){ 
      console.log('func1'); 
     }, 
     func2: function(){ 

     } 
    }, 
    subobj3: { 
     func3: function(){ 

     }, 
     func4: function(){ 
      this.parentObject.subobj2.func1(); 
     }   
    } 
    } 
    obj.subobj3.parentObject = obj; 
/* 
    //You can also init parentObject reference of the rest of the nested objects if you need 
    obj.subobj1.parentObject = obj; 
    obj.subobj2.parentObject = obj; 
*/ 
    return obj; 
}(); 

obj.subobj3.func4(); 

的想法是,嵌套的对象可以不知道谁是他们的父母,但家长可以告诉它的孩子是谁,他(但随后初始化代码。正如你在我的实现中看到的那样)。

你可以在这里进行测试:http://jsbin.com/eVOpITom/1/edit

2

下面是你可以用一个递归的init添加.parent任何子对象:

var obj = { 
    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; 
    }, 
    subobj1: { 
    }, 
    subobj2: { 
     func1: function(){ 
      console.log('hey'); 
     }, 
     func2: function(){ 
     } 
    }, 
    subobj3: { 
     func3: function(){ 
     }, 
     func4: function(){ 
      this.parent.subobj2.func1(); 
     }   
    } 
}.init(); 

obj.subobj3.func4(); 

有了这个解决方案,您还可以使用.parent多次你嵌套需要,类似的例子,因为如果你有两个嵌套层次:

this.parent.parent.subobjX.funcY(); 

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

1

正如其他人所说的,使用普通对象不可能从嵌套子对象中查找父对象。

但是,如果您使用递归ES6 Proxies作为助手,则可能会发生这种情况。

我写了一个名为ObservableSlim的库,它可以让您从子对象遍历到父对象。

下面是一个简单的例子(jsFiddle demo):

var test = {"hello":{"foo":{"bar":"world"}}}; 
var proxy = ObservableSlim.create(test, true, function(changes) { 
    console.log(JSON.stringify(changes)); 
}); 

function traverseUp(childObj) { 
    console.log(JSON.stringify(childObj.__getParent())); // returns test.hello: {"foo":{"bar":"world"}} 
    console.log(childObj.__getParent(2)); // attempts to traverse up two levels, returns undefined because test.hello does not have a parent object 
}; 

traverseUp(proxy.hello.foo);