How can I keep the context of 'this' in jquery - javascript

I have something like this:
var Something = function(){
this.render = function(){};
$(window).resize(function(){
this.render();
});
}
The trouble is that inside the anonymous function 'this' refers to the window object. I know I could do something like:
var Something = function(){
this.render = function(){};
var tempThis = this;
$(window).resize(function(){
tempThis.render();
});
}
but is there a better way? This doesn't look very elegant.

The solution you found is the the one most people use. The common convention is to call your tempThis variable "that."
var Something = function(){
this.render = function(){};
var that = this;
$(window).resize(function(){
that.render();
});
};

That looks like your best option, I don't think there's a better way. (someone correct my if I'm wrong).

FYI the ability to control this is coming in the next version of JQuery

I've been doing it this way in many tight situations. It doesn't look elegant, but it never fails. Actually thats javascript closures in action.
jrh

That's exactly what I do. It's not specific to jQuery, either.
var Construct = function() {
var self = this; //preserve scope
this.materials = 2000;
this.build = function(){
self.materials -= 100;
};
};
Remember to use the var keyword in front of your new scope variable. Otherwise, you're creating a new global variable. As a local variable, it will still be accessible inside the inner function via a closure.

The best solution, to keep variables at a minimum would be to use the Function.prototype.bind() method.
var Something = function(){
this.render = function(){};
$(window).resize( this.render.bind( this ) );
}
The problem with this method that may cause future complications, which means you should choose to use it sparingly, is when you need to invoke $(this) to grab the element. So, I might suggest that it would be worthwhile to use Function.prototype.bind() in your resize method, but it would not be a good solution to use it in a click function that you might need to target the clicked element directly.
See this JSFiddle for a working example.
See the Mozilla Documentation on Function.prototype.bind() for more information
The other methods are usable, but creating a variable to maintain the context of this is the undesired effect according to your question.

Related

Javascript call function with “this” on event [duplicate]

I have created a 'control' using jQuery and used jQuery.extend to assist in making it as OO as possible.
During the initialisation of my control I wire up various click events like so
jQuery('#available input',
this.controlDiv).bind('click', this, this.availableCategoryClick);
Notice that I am pasing 'this' as the data argument in the bind method. I do this so that I can get at data attached to the control instance rather from the element that fires the click event.
This works perfectly, however i suspect there is a better way
Having used Prototype in the past, I remember a bind syntax that allowed you to control what the value of 'this' was in the event.
What is the jQuery way?
You can use jQuery.proxy() with anonymous function, just a little awkward that 'context' is the second parameter.
$("#button").click($.proxy(function () {
//use original 'this'
},this));
I like your way, in fact use a similar construction:
$('#available_input').bind('click', {self:this}, this.onClick);
and the first line of this.onClick:
var self = event.data.self;
I like this way because then you get both the element clicked (as this) and the "this" object as self without having to use closures.
jQuery has the jQuery.proxy method (available since 1.4).
Example:
var Foo = {
name: "foo",
test: function() {
alert(this.name)
}
}
$("#test").click($.proxy(Foo.test, Foo))
// "foo" alerted
I don't think jQuery has a built-in feature for that. But you could use a helper construct like the following:
Function.prototype.createDelegate = function(scope) {
var fn = this;
return function() {
// Forward to the original function using 'scope' as 'this'.
return fn.apply(scope, arguments);
}
}
// Then:
$(...).bind(..., obj.method.createDelegate(obj));
This way, you can create dynamic 'wrapper functions' with createDelegate() that call the method with a given object as its 'this' scope.
Example:
function foo() {
alert(this);
}
var myfoo = foo.createDelegate("foobar");
myfoo(); // calls foo() with this = "foobar"
HTML 5-compliant browsers provide a bind method on Function.prototype which is, probably the cleanest syntax and is not framework-dependent, though it is not built into IE until IE 9. (There is a polyfill for browsers without it, though.)
Based on your example, you can use it like this:
jQuery('#available input',
this.controlDiv).bind('click', this.availableCategoryClick.bind(this));
(side note: the first bind in this statement is part of jQuery and has nothing to do with Function.prototype.bind)
Or to use slightly more concise and up-to-date jQuery (and eliminate confusion from two different kinds of binds):
$('#available input', this.controlDiv).click(this.availableCategoryClick.bind(this));
you can use the javascript bind method like this:
var coolFunction = function(){
// here whatever involving this
alert(this.coolValue);
}
var object = {coolValue: "bla"};
$("#bla").bind('click', coolFunction.bind(object));
jQuery does not support binds and the preferred way is to use functions.
Because in Javascript, this.availableCategoryClick does not mean calling the availableCategoryClick function on this object, jQuery advise to use this preferred syntax:
var self = this;
jQuery('#available input', self.controlDiv).bind('click', function(event)
{
self.availableCategoryClick(event);
});
OO concepts in Javascript are hard to understand, functionnal programming is often easier and more readable.
Seeing that functions changes scope, the most common way is to do it by hand, with something like var self = this.
var self = this
$('.some_selector').each(function(){
// refer to 'self' here
}

Javascript scope basics : .bind or self =this?

For me the below code do the same thing but I'm not totally sure so I would like to be sure:
var self = this;
this.param = 5;
var listener = sub.on('change', function() {
self.param = 10;
});
Is it identical to ?:
this.param = 5;
var listener = sub.on('change', function() {
this.param = 10;
}.bind(this));
They're not identical, but for your purposes in the example you posted they're close enough in that you get the same effect. The goal is to have a reference to the value of this outside the event handler later when the handler is actually invoked. Both of those alternatives have that effect.
The .bind() function does a few other things that won't make any difference in a simple case like this.
edit — and definitely note the fix that #deceze posted in his answer.
Here's an example of when the two are different: if the self variable were to change, then your event handler would behave differently. It's probably not very likely that you'd change it, but it's a possibility (a bug could be introduced). With .bind(), you get a function that really can't be changed; nothing can override the binding that you set up that way.
It should be:
sub.on('change', function() {
this.param = 10;
}.bind(this))
^
misplaced parenthesis
You want to bind this for the callback function, not for on(). If you fix that, the results will be the same for your purposes.
Please also consider that there is notable performance results from both (actually they are 3) ways.
Check out https://jsperf.com/bind-vs-self-closure/17
Doing a closured reference seems to be way faster (actually 100x) than binding context.

Why assign `this` to `self` and run `self.method()`?

I'm reading the source from mongoose
Collection.prototype.onOpen = function () {
var self = this;
this.buffer = false;
self.doQueue();
};
I don't understand why the author assigns this to self and runs self.doQueue(). Why not just run:
this.buffer = false;
this.doQueue();
I'm new to javascript, thanks for help.
You're right, in this instance they could have simply used this.
The use of me or self is a bit of a hack to ensure the correct context of this is used, as within JavaScript the scope of this is variant. If for example you have an event trigger a function within your class, this would be different, and wouldn't be your object that houses the function, but instead the object that called the function. To resolve this people often use me or self to ensure they're referring to the correct object... this, as in the actual object.
Just to give more clarity to #richard said earlier,
Collection.prototype.onOpen = function () {
var self = this;
this.buffer = false;
this.onclick = function(){
//do some other operations here
//if you refer `this` here then, `this` will refer to present function not the above. so to make sure it is referring to exact object people pass this to `me` or `self`
self.doQueue();
}
};
The only reason you would usually do that is if the call to doQueue() is inside a block that will change the value of this such as another function.
In this case however it doesn't serve any purpose and was probably a remnant of older code that was not changed back.
Most likely the developer wanted consistency, but failed at doing so.
Otherwise you'd be using this in some functions, self in other functions and a mix of both in other functions, depending on where you use the object and if you use nested functions/callbacks.
By always assigning this to self and then using the latter you have one additional assignment at the very beginning of each function but you always use self to access the object.
However, what the developer did in the code you posted does not make much sense. He should either use self or this both times instead of a mix that is not even necessary.
self is a copy of 'this',but it always refer to the right object,and 'this' may not.

Object oriented design in javascript and 'this' pointer

I am creating a object in javascript like this
function myobject() {
this.myvar1 = 0;
this.myvar2 = 0;
}
myobject.prototype.a = function(){
this.myvar1 +=1;
$('#button').click(function () { // 'this' is undefined
alert(this.myvar1)
})
}
var mything = new myobject();
mything.a()
What is the proper way to pass the this pointer to an anonymous function?
For updated question:
The issue is that inside that event handler, this refers to the element you clicked on, rather than your myobject, so just keep a reference to it, like this:
myobject.prototype.a = function(){
this.myvar1 +=1;
var self = this;
$('#button').click(function () {
alert(self.myvar1)
});
}
You can test it out here.
For previous question:
What you have should work (exactly as you have it), you can test it here.
Adding the following code to the end of your snippet and running it correctly alerts '1':
mything.b();
alert(mything.myvar1);
What were you expecting? Perhaps you're incorrectly invoking mything.b() ?
To pass this to an inner function, "save" it to another variable.
myobject.prototype.a = function() {
var self = this;
self.myvar1 += 1;
$('#button').click(function () {
alert(self.myvar1);
});
}
What's happening here is that jQuery is hijacking the value of this in the anonymous function used as a handler for the click event. It's kind of confusing, but jQuery's behavior is to assign the DOM element that triggered the event to this. There are a couple ways to set the value of this explicitly (the "context") for the callback function:
Function.prototype.bind - Part of the ECMAScript 5 standard, just starting to be implemented in browsers. For legacy support, you can extract it from the Prototype library.
$.proxy - jQuery's crappy equivalent of Function.prototype.bind, which was introduced in jQuery 1.4.
I wrote a couple posts on my blog that explain these in more detail if you're interested:
Organizing JavaScript with Namespaces and Function Prototypes
Understanding jQuery 1.4's $.proxy() method
In both cases, since this will now be your object and not the triggering DOM element, you can get the triggering DOM element by inspecting the event object, which will be the second parameter to your callback function.
Others here have done a nice job explaining the issue and how to resolve without adding any dependencies, but personally I think this plugin is a better overall solution (if you don't mind the dependency):
http://markdalgleish.com/projects/eventralize/

How to best use 'this' when its unavailable

say I create someObj like this
var someObj = function(){
var self = this;
//use this normally
document.body.addEventListener('click',function(){
//use self because this is unavailable
},false)
}
new someObj();
In the event this is not the someObj which id like to use but in this case the body element. Is there a best practice way to get someObj or is declaring some self var like in the example considered any good?
Using self seems fine to me.
You might also want to check out using call or apply (see for example odetocode and specifically about this in this post)
In my experience, declaring something like 'self' is the easiest way to do it.
I would consider your code to be perfectly acceptable.

Categories

Resources