I thought I’d got my head around context and scope in javascript. I don’t understand why in one situation proxy/bind works, and in another it doesn’t. Please could someone explain?
Example 1: Proxy (or bind) works:
function Cat(name){
this.name = name;
$("#cat").click(
$.proxy(
function(e){ this.meow(e); }
, this)
);
this.meow = function(){ alert(this.name + "says meow"); }
}
var cat = new Cat();
Example 2: Proxy and bind don’t work:
function Dog(breed){
this.breed = breed;
this.save = function(){
var that = this;
$.ajax({
url: '/ajax/savedog.php', dataType: 'json',
// This works?? Shouldn't scope be of .ajax()?
data: this.breed,
// success: $.proxy(... // won't work? why?
success: that.dogSaved, error: ajaxFail
});
};
this.dogSaved = function(){ alert("Dog Saved"); }
}
var dog = new Dog();
You’re copying
thistothatinside the “click” handler. Do it outside.The value of
thisis set anew for and upon each function call. Thus, inside your “click” handler,thisis not a dog, it’s a DOM element.It’s also important to be mindful of the order of evaluation in JavaScript. Parameters to functions are fully evaluated in the context of the calling environment. In your first example, the value of
thispassed in to$.proxy()is the correct one because it’s a parameter in the context of theCatconstructor, and thus it is correctly a cat. In your call to$.ajaxin theDogconstructor, however, the reference tothis.breedwill not have the correct value, as it is evaluated in the context of the “click” handler and not the constructor. The value of the “data” property should bethat.breedonce you’ve fixed the initialization ofthatas described above.(Also note that as @Musa points out, the
Dogconstructor is syntactically incorrect; I assume that was just a transcription error.)edit — I’m not sure what you’re trying with
$.proxy()in your updated question, but that “success” property should work if you set it up like this:The first argument to
$.proxy()is the function to be called, and the second is the value you want forthiswhen the function is called. In this case, you want it to be the saved reference to the dog object. Note, however, that it will only work if the “save” function is called withthisset to a dog. That is, if somewhere you do this:then things should work. However, if you somehow use that “save” function in some way such that
thisis not a reference to a dog, then it won’t work. Again, if in the “Dog” constructor you were to move that declaration of “that” out to the constructor scope instead of in “save”, then it won’t matter how “save” is called because “that” will always be a reference to the dog object.