-2

When creating a pointer to a function inside an object "this" is not correctly resolved
Try this example to get the concept...

// this.* fail
a = { x : 123,  f : function(){ console.log( this.x ) } }
a.f()     // 123
b = a.f   // b points to a.f now
b()       // should print 123 but gaves 'undefined'
  • of course we could force the resolution using the object name instead of "this"
    but then we loose funcionality...
ZEE
  • 2,931
  • 5
  • 35
  • 47

4 Answers4

2

From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this.

Function context

Inside a function, the value of this depends on how the function is called.

Simple call

function f1(){
  return this;
}

f1() === window; // global object

This is what you are doing in the 2nd case b(). You are basically calling x on the global object. So

var x = 456;
// this.* fail
a = { x : 123,  f : function(){ console.log( this.x ) } }
a.f()     // 123
b = a.f   // b points to a.f now
b()       // prints 456

As an object method

When a function is called as a method of an object, its this is set to the object the method is called on.

In the following example, when o.f() is invoked, inside the function this is bound to the o object.

var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

console.log(o.f()); // logs 37

This is what happens in the first case.

potatopeelings
  • 40,709
  • 7
  • 95
  • 119
2

You can use bind:

b = a.f.bind(a);
b(); // 123

From MDN:

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

Artem
  • 1,773
  • 12
  • 30
1

when you invoke a method on an instance, the context of the method is the instance (the this keyword in the f method is a reference to a when doing a.f()).

However, when you keep the reference to the function in a variable, when invoking it, you actually lose the context, so this becomes the global context (which is window in a browser).

So, you need to give the context to the function when you are invoking it thanks to call or apply methods:

Function.prototype.call

Function.prototype.apply

Your code becomes:

b = a.f;
b.call(a); // or b.apply(a)
Benoit
  • 751
  • 5
  • 8
  • Or use `bind`. `this` depends entirely on how the function is called, it won't necessarily be the global context, either. – Dave Newton Aug 08 '15 at 11:53
1

You can try to assign this to some variable in an object:

var a = {
   x : 1,
   self : this,
   f : function() {
      self.x++;       
   },
   show : function() {
      alert(self.x);
   }
}

a.f();    
a.show();      

d = a.show;
d();     
Damian0o
  • 653
  • 5
  • 15