You can use something like that bind function, but you don't really need it.
In most cases it's simpler to use a closure.
 
That's the basis of the good solution that Brian gave you, although there
was a critical error in the code, a missing "var" on the "obj = this;"
statement.
 
Let's correct that and take another look at the code:
 
var MyClass = function(selector)
{
    var obj = this;
    obj.hello = 'Hello World!';
 
    alert('loaded: this = ' + obj);
    alert(obj.hello);
 
    var onClick = function()
    {
        alert('onclick: this = ' + obj);
        alert(obj.hello);
        otherFunc();
    }
 
    var otherFunc = function()
    {
        alert('otherfunc: this = ' + obj);
        alert(obj.hello);
    }
 
    $(selector).bind("click", onClick);
};
 
I believe that is nearly identical to your original code; the only
difference is that all the references to "this" are changed to "obj", and
there's a "var obj = this;" added at the beginning.
 
"obj" is not a magic keyword; it's simply the name of a local variable. You
can use any name you like here. By saving "this" in a local variable, it
becomes available to all nested functions.
 
It's really very simple and accomplishes what you were trying to do, and
more simply than a Prototype-style bind.
 
"this" is special: its definition depends on how a function was called.
Using a local variable avoids that issue; it is available in nested
functions regardless of how they are called.
 
-Mike



  _____  

From: jquery-en@googlegroups.com [mailto:[EMAIL PROTECTED] On
Behalf Of Hector Virgen
Sent: Monday, November 10, 2008 7:47 PM
To: jquery-en@googlegroups.com
Subject: [jQuery] Re: Trouble with "this"


Maybe what I am looking for is something similar to this: 

http://www.prototypejs.org/api/function/bind


-Hector



On Mon, Nov 10, 2008 at 7:45 PM, Hector Virgen <[EMAIL PROTECTED]> wrote:


Thank you for the replies. I thought I knew Javascript until just recently
when I started using jQuery, and things started to behave differently than
I'm used to.  

So let me see if I understand this...

var MyClass = function(selector)
{
    this.hello = 'Hello World!'; 
}

So, "this" is equal to "window"? If so, what is the difference between the
code above and:


var MyClass = function(selector)
{
    window.hello = 'Hello World!'; 
}

My goal is use "this" as the instantiated object, not just a reference to
the class itself. If I were to call the onClick function *without* the event
triggering it, it would behave as expected -- "this" always means the
instantiated object.

Is there a way to bind (as in, jQuery#bind()) an event listener without
changing the meaning of "this"? Is this how I would do that?

$myInstance = new MyClass();


$('#clickme').click(function() {
    MyClass.call($myInstance);

});


How do I tell it to call the onClick method?

-Hector 



On Mon, Nov 10, 2008 at 7:18 PM, RobG <[EMAIL PROTECTED]> wrote:





On Nov 11, 11:17 am, "Hector Virgen" <[EMAIL PROTECTED]> wrote:
> I'm having trouble using "this" in my objects when the method is triggered
> by an event.


The value of a function's this keyword is *always* set by the call, so
use the call to set it to the value you want.



> Here's my basic test class. The lines that do not work as expected are in
> red.
>
> var MyClass = function(selector)
> {
> this.hello = 'Hello World!';


If you call the function as MyClass(...), its this keyword will be the
global/window object, so you have just assigned the string "Hello
World!" to a hello property of the window object.  Test it:

 alert( window.hello );  // shows 'Hello World!'



>  var onClick = function()
> {
> alert('onclick: this = ' + this); // <-- object HTMLInputElement


When a listener is called, it is traditional for its this keyword to
refer to the element that the listener was attached to.  The call is
made by the browser, so it calls the function in a way that sets its
this keyword to the element that the listener is attached to.  You
can't change that, but you can do something like:

 <input ... onclick="MyObject.call( /* the object you want set as
MyObject's this keyword */ );">



> alert(this.hello); // <-- does not work: undefined


It works as designed: the HTML element doesn't have a hello property.
You created the hello variable as a property of the window object.


> otherFunc();}

This creates a closure with the outer function's otherFunc variable so
that when the element is clicked, otherFunc is called. Since the call
is unqualified, otherFunc's this keyword will be the global/window
object.



>  var otherFunc = function()
> {
> alert('otherfunc: this = ' + this); // <-- object Window ??


Yes, because of the way otherFunc was called.



> alert(this.hello); // <-- does nto work: undefined}


It does work, just no as you expected.



>  $(selector).click(onClick);
>  alert('loaded: this = ' + this); // <-- object Object


Nope, window object.



> alert(this.hello); // <-- alerts "Hellow World!"


Yep, it's reporting the value of window.hello as described above.



> };
>
> The way this works is instantiating a new MyClass object


It declares a global variable called MyClass.  When the code is
executed, it is assigns a reference to the function object created by
the function expression on the right hand side.  There is no
"instatiating", declaring a variable and assigning it a value in one
statement is generally called initialising.



> binds the click event to the selector.


Adds a listener, it doesn't "bind" anything.



> This works fine, but "this" loses its scope, even
> when calling other functions.


A function's this keyword has nothing to do with scope, it is set by
the call, not by the declaration or initialisation.



> To see this in action, check out this page (watch out for the alerts ;)).
>
> Any ideas on how to keep "this" within scope?


Set it to the value you want when you call the function.  What do you
expect it to refer to?


--
Rob



Reply via email to