2

Typically, calling this would work; but I am calling the method in another context, so this refers to that context rather than the 'parent' object.

Here's the code:

var someConfig = {
  things: [
    {
      attr1: 'foo',
      attr2: 'bar',
      action: function() {
        console.log(this);
      }
    }
  ]
}

function Constructor(config) {
  var self = this;
  self.name = 'test';
  self.things = config.things;

  $.each(self.things, function(i, thing) {
    thing.action();
  });
    }

var obj = new Constructor(someConfig);
console.log(obj);

Here's a jsfiddle. The goal is to have both objects that are in the console to be the same, but this in the context of the action method returns the original object to which action belongs, rather than the constructor.

The only thing I can think of is to pass self into action, but I think there's a better way.

Sam Selikoff
  • 11,238
  • 9
  • 54
  • 94

3 Answers3

3

Firstly, a couple of points about your code. your config property is uniqueAction yet later you refer to it as config.action. When you call obj.action you need to call it as a function like: obj.action();

With that in mind, the following seems to do what you require...

var config = {
  action: function() {
    console.log(this.name);//<- IMPORTANT PART
  }
}

function Constructor(config) {
  var self = this;
  self.name = 'test';
  self.action = config.action;
}

var obj = new Constructor(config)
obj.action();

Notice that the console.log call now uses this.name instead of self.name.

Here is a working example

musefan
  • 45,726
  • 20
  • 123
  • 171
  • Thanks for the edits, I fixed my code. Also, I wasn't specific enough. `this` doesn't work because I'm calling the function in another context. I also updated my code to reflect this. – Sam Selikoff Jan 10 '13 at 16:34
  • @SamSelikoff: Please create a [http://jsfiddle.net/](JSFiddle) that demonstrates it not working – musefan Jan 10 '13 at 16:37
  • @SamSelikoff: In your case, `this` actually _does_ work. When you call `obj.action()`, `this` will reflect `obj`. Which is exactly what you’re after, no? – Martijn Jan 10 '13 at 16:38
  • @Martijn Sorry, I think my link was bad - I fixed it. The console shows `Object` then `Constructor`. The goal is to have the first line also be `Constructor`. – Sam Selikoff Jan 10 '13 at 17:02
1

Can functions passed into constructors have access to the constructor's other properties?

Yes, but only if you pass that object to the function (or implicitly use the this keyword).

What you did try was accessing the local self variable from a function that was declared outside the constructor, which is just impossible.

So just use

{
  action: function() {
    console.log(this.name);
//              ^^^^
  }
}

And when calling obj.action() the this will point to the instance.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
1

The only way I see is to tack the 'constructor' onto the config thing before calling the action.

Check out this Fiddle, which was forked off yours. I've changed two things:

First, the action function no longer references this, but rather the property parent of this.

  action: function() {
    console.log(this.parent);
//                  ^^^^^^^
  }

Second, each thing object receives a parent property, which references self.

  $.each(self.things, function(i, thing) {
    thing.parent = self;
    thing.action();
  });
Martijn
  • 12,254
  • 3
  • 46
  • 58
  • Thanks. This makes sense to me. I'm a newbie to OOP, so I guess my question is, is this bad design on my part, or just a javascript peculiarity? I would typically expect an object's methods to have access to all of the object's data. Should I be extending here? – Sam Selikoff Jan 10 '13 at 17:22
  • Well... Considering that (in Javascript) a single function could be a property tacked onto several different objects _at the same time_, which object's data should it refer to? – Martijn Jan 10 '13 at 17:28
  • 1
    In this case, I think I’d copy the members of `things` directly onto `self`, so that you can simply use `this` in the functions. Extending would be a better way to go here (put them on `Constructor`'s `prototype`). – Martijn Jan 10 '13 at 17:30
  • How do you copy onto self? That's what I'm trying to do here: `self.action = config.action;`. – Sam Selikoff Jan 10 '13 at 17:35
  • 1
    If you use `self.action = config.action`, then it’ll work with just `this`. However, you assigned `action` to a _different_ object than `self`, which is why I had to use that workaround in my answer. (See [here](http://stackoverflow.com/questions/5429739/this-keyword-not-clear/5429817#5429817) for a little explanation of the *this* keyword). – Martijn Jan 10 '13 at 17:40