Like Dave said, closures may be hard to understand at first, but it
is, in fact, one of the most important thing to understand when
writing JS scripts. Consider this :

----------------------------------------------------
var AjaxEngine = Class.create();
ajaxEngine.prototype = {

  initialize: function(id) {
    this.id = id;
  },

  request: function(url, callback) {
    var options = {
      method: 'get',
      onSuccess: function() { callback(this.id); }
    };

    new Ajax.Request( url, options );
  }
};

var successFn = function(id) {
  alert( id );
};

new AjaxEngine("test").request( "page.php", successFn );
----------------------------------------------------

(Let suppose the file page.php exists on the server, and the onSuccess
method of the ajax request is executed)
What do you think will be the output printed in the alert box ?

If you say "test", guess again. Why ? Who called the onSuccess
function ? The object AjaxEngine never calls anything except the
method Request of the new Ajax object (new Ajax.Request...). In fact,
it is that Ajax object who called it, so the keyword 'this' refers to
that object. For this reason, 'this.id' is 'undefined'.

Therefore, in this particular script, it is impossible to know what
AjaxEngine object was successful. To return the information we need,
we must "bind" the function so it will always be called in a
particular context. Fortunatly, Prototype offers that function :
bind(), which is a member of the Function prototype. Consider
replacing the line :

     onSuccess: function() { callback(this.id); }

by

     onSuccess: function() { callback(this.id); }.bind(this)

Since the onSuccess assignement is executed in context of the
AjaxEngine (we called new AjaxEngine().request....) then the binding
is done with the AjaxEngine object (this). For this reason, the 'this'
inside the function, however the function may be called, is always the
same this as the one 'this' used to bind the function with. With this
modification, the alert will display "test".

The keyword 'this' always refers to the exact object used to call the
function. As this :

var Example = function(id) {
  this.id = id;
};
Example.prototype = {
  func: function() {
    alert(this.id);
  }
}

var obj1 = new Example("test1");
var obj2 = new Example("test2");

obj1.func();     // will output "test1"
obj2.func();     // will output "test2"
obj1.func.bind(obj2).call();  // will output "test2" because of
binding


I suggest you familialize yourself with closures and binding, so you
will minimize the chance your code will be messy, hard to maintain,
and cause memory leaks.


-yanick


On 12 avr, 05:36, Dave Crane <[EMAIL PROTECTED]> wrote:
> Hi,
>
> Use a closure - if you reference the variable a inside the anonymous function
> assigned to the onSuccess callback, the interpreter will preserve a reference
> to it.
[snip]


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Spinoffs" group.
To post to this group, send email to [EMAIL PROTECTED]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to