0

I have a resource object like so:

var resource = {
    ...
    All sorts of nifty stuff;
    ...
};

I'd like to create a function expression on the fly and refer to other functions in my resource object with the keyword this:

resource.url = function(){
    return this.constructbaseUrlParams() +
           this.constructReqeustParams();
}();

but this refers to the window object here.

I know I can use:

resource.url = function(){
    return resource.constructbaseUrlParams() +
           resource.constructReqeustParams();
}();

But I'd like to use this so the function can be more modular and perhaps allow me to create multiple resource objects in the future without issue.

How can I use this inside my function expression and still refer to my object?

Community
  • 1
  • 1
agconti
  • 17,780
  • 15
  • 80
  • 114
  • 1
    the value of `this` is totally dependant on how the function is called, not how it was created. – adeneo Apr 18 '14 at 20:59
  • @adeneo I'm aware. how can I call the functions within whateverObject.url and still refer to whateverObject? – agconti Apr 18 '14 at 21:01

4 Answers4

2

Use call to specify a value for this inside:

resource.url = function(){ ... }.call(resource);

Or use bind.

var fn = function() { ... }.bind(resource);
resource.url = fn();
guest
  • 6,450
  • 30
  • 44
2

The value of this is determined by how the function is called.

And, the IIFE isn't being called with any associated context object. It's simply defaulting to the global object, window.

You can specify the context of the IIFE with .call():

resource.url = function () {

    console.log(resource === this); // true

    return this.constructbaseUrlParams() +
           this.constructReqeustParams();

}.call(resource);
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
1

You could create a new url function on the object instead of directly invoking it:

var resource = {
   foo: function() {
      console.log('foo');   
   } 
};

resource.url = function() {
    this.foo();   
}

resource.url(); //foo 

Additionally if you want to easily create new instances of a resource with maybe different url functions you could move the resource object in a function:

function Resource() {
    return {
        foo: function() {
            console.log('foo');   
        }
    }
}

var r1 = new Resource();
var r2 = new Resource();

r1.url = function() {
    this.foo();   
}

r1.url(); //foo
r2.url(); //undefined
Marcel Gwerder
  • 8,353
  • 5
  • 35
  • 60
  • That doesn't make a difference. Making `url` a function instead of a string does. – Bergi Apr 19 '14 at 11:41
  • I'm not sure what you want to tell me. Or lets say I have no idea. Can you extend this a bit? – Marcel Gwerder Apr 19 '14 at 11:50
  • You say that "*moving the resource object in a function*" will solve the problem. I say that your solution actually was to make `url` a method - `ressource` could have stayed an object literal. – Bergi Apr 19 '14 at 11:52
  • Ok I see what you mean. I was so sure I tried that and it didn't work. I'll try to improve the answer thanks. – Marcel Gwerder Apr 19 '14 at 11:58
0

Resource could be turned into a class.

function Resource() {
    this.constructbaseUrlParams = function() {
        return "test";
    };

    this.constructReqeustParams = function() {
        return "test2";
    };

    this.url = function() {
        return this.constructbaseUrlParams() +
               this.constructReqeustParams();
    }
};

var resource = new Resource();
console.log(resource.url());
Tony Zampogna
  • 1,928
  • 1
  • 12
  • 14