javascript获取父嵌套对象?

Posted

技术标签:

【中文标题】javascript获取父嵌套对象?【英文标题】:javascript get parent nested object? 【发布时间】:2012-11-12 02:49:48 【问题描述】:

我有一个像这样的对象,例如:

obj = 
    subobj1: 

    ,
    subobj2: 
        func1: function()

        ,
        func2: function()

        
    ,
    subobj3: 
        func3: function()

        ,
        func4: function()

                
    ,

如何从 func4 中调用 func1 而无需调用 obj.subobj2.func1() ?

【问题讨论】:

【参考方案1】:

你不能完全正确。您无法知道您的函数存在于哪些对象中。

请注意,它可能不止一个:您可以在现有代码之后编写此代码:

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。

【讨论】:

有this.parent.func1()这样的函数吗? 您不能只在对象声明中设置变量。这不起作用 嗯,有道理,从工厂外调用 subobj2.func1 是不是必须调用 obj.that.suboj2.func1? 否:您可以直接致电obj.suboj2.func1();。事实上parent(上次编辑之前的“那个”)是私有的:如果它不是简单的 obj,你就不能在工厂外调用它。【参考方案2】:

以下是如何将.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

【讨论】:

这看起来是最干净的工作解决方案,我使用它并且非常喜欢它。另外,嵌套.parent 非常有用。 将属性分配给 null 时收到错误消息。修复了将 if (typeof this[i] == 'object') 替换为 if (typeof this[i] == 'object' && this[i] !== null)【参考方案3】:

您不能直接这样做,因为没有办法像在文件系统中使用“..”那样“向上”对象层次结构。

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

obj = (function()

    var obj1 = ...
    var obj2 = ...

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

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

在本例中,内部函数可以直接从它们的变量中访问obj1obj2func3func4。自调用函数使这些内部变量是私有的并且对外部隐藏,并且 return 语句允许您仅导出要公开的函数。

【讨论】:

【参考方案4】:

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

但是,如果您使用递归 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);

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

这里有一个更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);

请记住,一个对象不能有多个父对象。

【讨论】:

【参考方案7】:

您对对象的实现是不可能的。取决于您的需求 - 以下实现可能很有用:

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

这个想法是嵌套对象不能知道谁是它们的父对象,但父对象可以告诉它的子对象他是谁(但随后需要 init. 代码,正如您在我的实现中看到的那样)。

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

【讨论】:

以上是关于javascript获取父嵌套对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何从嵌套的对象数组中获取每个父级的值

如何为嵌套对象或同一父对象中的对象列表定义 GraphQLObjectType

JavaScript 访问父对象属性

javascript Lodash获取嵌套对象值

如何用javascript 跨域获取iframe子页面的元素信息

JavaScript:将具有父键的对象数组转换为父/子树(包括没有父的对象)