在JavaScript中,您如何到达这个'外部对象的对象,来自对象的方法,该对象是外部对象中数组的元素

时间:2014-05-01 16:33:04

标签: javascript oop closures

我有一个像这样创建的JavaScript对象:

var outer = {
    list: [
        {
            field1: 111,
            field2: 222,
            doSomething: function() {
                var x =id;
            }
        },
        {
            field1: 333,
            field2: 444,
            doSomething: function() {
                var x =id;
            }
        } 
    ],

    id: 0,
};

让我们说一下list的第一个元素的doSomething()被调用。 在doSomething()中,我可以访问this.field1,并读取并获取值111,因为在该上下文中这是doSomething()是方法的对象。 但是,整个列表数组是外部对象的成员。外部的另一个成员是id,它是列表的兄弟。如何从任何doSomething()方法的内部变量中访问id?我唯一能想到的是使用语法:     var x = outer.id; 但是知道该特定实例的变量名称的方法。

所以我必须创建一个函数来创建其中一个,并在该函数中使用一个临时变量分配给该对象,并在doSomething()中引用该变量。

这是最好的方法吗?

[编辑] 我上面提到的我提出的解决方案看起来像这样:

var outer = {
    list: [
        {
            field1: 111,
            field2: 222,
            doSomething: function() {
                var x =outer.id;
            }
        },
        {
            field1: 333,
            field2: 444,
            doSomething: function() {
                var x =outer.id;
            }
        } 
    ],

    id: 0,
};

我试图避免内部物体知道标识符"外部" ...但我想这是我们能做的最好的 - 而且可能足够好

4 个答案:

答案 0 :(得分:0)

添加另一个包含对包含对象的引用的属性。

var outer = {
    list: [
        {
            field1: 111,
            field2: 222,
            doSomething: function() {
                var x = this.container.id;
            }
        },
        {
            field1: 333,
            field2: 444,
            doSomething: function() {
                var x = this.container.id;
            }
        } 
    ],

    id: 0,
};
for (var i = 0; i < outer.list.length; i++) {
    outer.list[i].container = outer;
}

答案 1 :(得分:0)

我认为你的问题太复杂了。如果id中每个项目的list相同,那么它不需要包含在对象outer中。你可以简单地引用这样的id:

var id = 0;

var outer = {
    list: [
        {
            field1: 111,
            field2: 222,
            doSomething: function() {
                var x = id;
                console.log(x);
            }
        },
        {
            field1: 333,
            field2: 444,
            doSomething: function() {
                var x = id;
                console.log(x);
            }
        } 
    ]
};

outer.list[0].doSomething();
outer.list[1].doSomething();

您甚至可以扩展doSomething函数以获取参数,然后根据需要为列表中的每个项目传递不同的值:

doSomething: function(x) {
    console.log(x);
}

然后你会这样称呼:

outer.list[0].doSomething(0);
outer.list[1].doSomething(1);

答案 2 :(得分:0)

JavaScript中没有向上关系,因为&#34; child&#34;对象可以有多个父母&#34;对象:

var outer = {
  inner = {"foo": "bar"}
};

var newOuter = {};
newOuter.inner = outer.inner;

// now inner is a property of both outer and newOuter

由于您无法使用thisthis.parent等关键字直接访问外部上下文,因此您必须使用其他选项。最好的办法是将上下文(this)作为参数传递给doSomething方法:

var outer = {
  list: [
    {
      field1: 111,
      field2: 222,
      doSomething: function(context) {
        var x = context.id;
      }
    },
    {
      field1: 333,
      field2: 444,
      doSomething: function(context) {
        var x = context.id;
      }
    } 
  ],
  id: 0,
};

outer.list[0].doSomething(outer);

正如其他人所提到的,您可以选择将id或上下文存储为list中内部对象的属性。这种方法的缺点是它生成重复的代码,这不是最佳的。

var outer = {
  list: [
    // version that stores context
    {
      context: outer,
      field1: 111,
      field2: 222,
      doSomething: function() {
        var x = this.context.id;
      }
    },

    // version that directly stores id
    {
      id: outer.id,
      field1: 333,
      field2: 444,
      doSomething: function() {
        var x = this.id;
      }
    } 
  ],
  id: 0,
};

您的第三个选择是使用JavaScript的变量范围规则将外部id存储在最外层范围内的变量中,从而使所有内部方法都可以访问:

var outer = {
  list: [
    {
      field1: 111,
      field2: 222,
      doSomething: function() {
        var x = id;
      }
    },
    {
      field1: 333,
      field2: 444,
      doSomething: function() {
        var x = id;
      }
    } 
  ],
  id: 0,
};

var id = outer.id;

这样做的主要缺点是,它可能会使用不需要的变量污染您的外部范围,并打开内部对象,直至id被更改的不良副作用。

TL; DR:

通常,面向对象编程的好处是模块化和封装:无论您在程序的其他部分中做出哪些更改,您都希望各种对象能够继续快速运行。因此,最好通过将一个对象作为方法调用中的参数传递给另一个对象来处理对象之间的通信,从而允许您将每个对象的逻辑与其他对象分开。因此,我建议定义内部对象,使doSomething()方法接受outer对象的所需上下文作为参数;这将使您的代码保持可扩展性,灵活性和干燥性。

答案 3 :(得分:0)

您可以从JavaScript中使用类中受益:

function Outer(id) {
    this.id = id || 0;
    this.list = [];
}

Outer.prototype = {
    constructor: Outer,

    addItem: function(item) {
        item.outer = this;
        this.list.push(item);
    }
};

function Item(outer) {
    this.outer = outer || null;
}

Item.prototype = {
    field1: null,
    field2: null,
    outer: null

    constructor: Item,

    doSomething: function() {
        alert(this.outer.id);
    }
};

使用:

var outer = new Outer(23);
outer.addItem(new Item());
outer.list[0].doSomething(); // alerts 23