2

Consider the following object:

var obj = {
  name: "pete",
  funct : function () { console.log("I am", this); }
}

When binding obj.funct to an event handler, this looses its reference to the object, it now refers to the global object (window).

so, this does not work properly:

$(window).bind("keypress", obj.funct);

How can I archieve that this still points to my object when it is called by an event handler?

Anton Harald
  • 5,772
  • 4
  • 27
  • 61

2 Answers2

1

Make a scoped variable referring to this.

var that = this;
var obj = {
  name: "pete",
  funct : function () { console.log("I am", that); }
}

or you can take another approach

var HoldAllValues = function(){
  var origin = this;
  this.name = "pete",
  this.funct = function () { console.log("I am", origin.name);origin.name = 'amnesia'; }
}
var gatekeeper = new HoldAllValues();
$(window).bind("keypress", gatekeeper.funct);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Tschallacka
  • 27,901
  • 14
  • 88
  • 133
  • Whilst this will work, I've always thought of this as an anti-pattern. If only lexically, it's not intuitive that "this" would be the same as "that." – Mitya May 28 '15 at 12:54
  • It's making use of a javascript feature. In essense you are referring to the origin object when passing the object around through different objects. It's only a matter of getting used to. This way you can have access to the this variable of the current object, and push alterations back to the origin object without having to use registries to maintain coherency. – Tschallacka May 28 '15 at 12:55
  • Yeah I know how it works - I was just speaking in terms of it being unintuitive, if only in the English language, for "that" to refer to the same thing as "this". – Mitya May 28 '15 at 12:56
  • 1
    But it doesn't. In your posted example this === jQuery and does not equal the origin object. The moment you "pass on" the object, by a click handler, load handler, ajax load handler, your this changes. It's only proper that your this reference references the current working object. And that, or whatever you want to call it(origin, father, mother, creator) references the originating object. I prefer calling it that because many developers use it for this purpose, but if you want to be inituitive you can give a more "logical" name. – Tschallacka May 28 '15 at 12:59
  • I added a new example to my answer where I use that/origin within a scope. – Tschallacka May 28 '15 at 13:05
  • Actually, you're quite right. I should have thought about it more. – Mitya May 28 '15 at 14:55
0

Use bind and pass this:

var obj = {
  name: "pete",
  funct : function () { console.log("I am", this); }.bind(this)
}
Amir Popovich
  • 29,350
  • 9
  • 53
  • 99
  • 1
    `bind` is an option. But `this` in your code refers to the `window` object! `$(window).bind("keypress", obj.funct.bind(obj));` – Ram May 28 '15 at 12:53
  • @Vohuman Use jquery `$.proxy()` instead of `Function.prototype.bind()`, so you could removed referenced handler later, which is not possible using `.bind()`. `$(window).bind("keypress", $.proxy(obj.funct, obj));` and if needed later: `$(window).unbind("keypress", $.proxy(obj.funct, obj));` – A. Wolff May 28 '15 at 13:01
  • @A.Wolff Context determines. `$.proxy` is _another_ option. – Ram May 28 '15 at 13:20
  • @Vohuman When it comes to event using refrenced method as handler, we shouldn't use `Function.prototype.bind()`. See e.g: http://jsfiddle.net/4wsxg9pw/ more relevant here: http://jsfiddle.net/4wsxg9pw/1/ – A. Wolff May 28 '15 at 13:26
  • @A.Wolff Because you can't unbind the handler? http://jsfiddle.net/4wsxg9pw/2/ – Ram May 28 '15 at 14:01