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

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

obj = {
    subobj1: {

    },
    subobj2: {
        func1: function(){

        },
        func2: function(){

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

        },
        func4: function(){

        }        
    },
}

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

【问题讨论】:

    标签: javascript oop object


    【解决方案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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-10-14
              • 1970-01-01
              • 2018-07-24
              • 2015-11-15
              • 2021-02-07
              • 2020-03-20
              • 1970-01-01
              • 2018-05-10
              相关资源
              最近更新 更多