简体   繁体   English

在JavaScript中,如何从作为外部对象中数组元素的对象的方法到达外部对象的“ this”对象

[英]In JavaScript, how do you get to the 'this' object of the outer object, from a method of an object that's an element of an array in the outer object

I have a JavaScript object created like this: 我有一个这样创建的JavaScript对象:

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

    id: 0,
};

Let's say doSomething() of the first element of list is called. 假设list的第一个元素的doSomething()被调用。 Inside of doSomething(), I can access this.field1, and read and get the value 111 because this in that context is the object that doSomething() is a method of. 在doSomething()内部,我可以访问this.field1,并读取并获取值111,因为在这种情况下,这是doSomething()是其方法的对象。 However the entire list array is a member of the outer object. 但是,整个列表数组是外部对象的成员。 Another member of outer is id, which is a sibling of list. 外部的另一个成员是id,它是list的同级。 How do I access the id from variable of outer from inside of any of the doSomething() methods? 如何从任何doSomething()方法内部的外部变量访问id? The only thing I can think of is to use the syntax: var x = outer.id; 我唯一想到的就是使用语法:var x = external.id; but the method that has knowledge of the name of the variable of that particular instance. 但是知道该特定实例的变量名称的方法。

So I have to create a function that makes one of these things, and use a temporary variable inside that function that's assigned to the object, and refer to that variable within doSomething(). 因此,我必须创建一个实现这些功能之一的函数,并在该函数中使用分配给该对象的临时变量,并在doSomething()中引用该变量。

Is that the best way? 那是最好的方法吗?

[edit] My proposed solution I mentioned above would look like this: [编辑]我上面提到的建议解决方案如下所示:

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,
};

I'm trying to avoid the inner objects from knowing the identifier "outer"... but I guess that's the best that we can do --- and probably good enough. 我试图避免内部对象知道标识符“外部” ...但是我想那是我们可以做的最好的事情,而且可能还足够好。

Add another property that contains a reference to the containing object. 添加另一个属性,该属性包含对包含对象的引用。

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

I think you're over complicating the problem. 我认为您已经使问题复杂化了。 If id is the same across each item in list , then it doesn't need to be contained inside the object outer . 如果idlist每个项目上都是相同的,那么它不需要被包含在outer对象中。 You can simply reference id like this: 您可以像这样简单地引用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();

You can even extend your doSomething function to take an argument and then pass a different value for each item in your list if you want: 您甚至可以扩展doSomething函数以接受参数,然后根据需要为列表中的每个项目传递一个不同的值:

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

Then you would call it like this: 然后,您将这样称呼它:

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

There is no upwards relationship in JavaScript because "child" objects can have more than one "parent" object: JavaScript中没有向上关系,因为“子”对象可以有多个“父”对象:

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

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

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

Since you cannot directly access the outer context with a keyword like this or this.parent , you must make use of other options. 由于您不能使用thisthis.parent这样的关键字直接访问外部上下文,因此必须使用其他选项。 Your best bet is to pass the context ( this ) to your doSomething method as an argument: 最好的选择是将上下文( 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);

As others have mentioned, you can alternatively store id or the context as attributes of inner objects in list . 正如其他人提到的那样,您可以将id或上下文作为内部对象的属性存储在list The downside of this method is that it generates repeated code, which is less than optimal. 这种方法的缺点是它会生成重复代码,这不是最佳方法。

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,
};

Your third option would be to use JavaScript's variable scoping rules to store the id of outer in a variable in the outermost scope, thereby making it accessible to all of the interior methods: 您的第三个选择是使用JavaScript的变量作用域规则,将external的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;

The main downside of this is that it can potentially pollute your outer scope with unwanted variables and open your internal objects up to unwanted side-effects of id being changed. 这样做的主要缺点是,它可能会用不需要的变量污染外部作用域,并使内部对象容易受到id更改所带来的有害副作用的影响。

tl;dr: tl; dr:

In general, the benefits of Object-oriented programming are modularity and encapsulation: you want your various objects to be able to continue functioning merrily on regardless of changes you make in other parts of your program. 通常,面向对象编程的好处是模块化和封装:您希望各种对象都能继续愉快地工作,而不管对程序其他部分所做的更改。 As such, communication between objects is best handled by passing one object to another as an argument in a method call, thereby allowing you to keep the logic of each object separate from the others. 这样,通过在方法调用中将一个对象作为参数传递给另一个对象,可以最好地处理对象之间的通信,从而使您可以将每个对象的逻辑与其他对象分开。 As such, I would recommend defining your inner objects such that the doSomething() method accepts the desired context of the outer object as an argument; 因此,我建议您定义内部对象,使doSomething()方法将所需的outer对象上下文作为参数接受; this will keep your code extensible, flexible, and DRY. 这将使您的代码可扩展,灵活且干燥。

You could benefit from using classes in JavaScript: 您可以从使用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);
    }
};

And to use: 并使用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM