Closures - referencing "this" at function creation, rather thanfunction call time.

L

lister

Hi folks, newbie(ish) here.

I want to attach an event handler to a google map marker. I want the
event handler to call into a member function of the object that
created it.

eg.

MyMarkerClass.prototype.registerEventHandler()
{
GEvent.addListener(this.GoogleMarker, "click", function()
{
this.onClick();
});
}

MyMarkerClass.prototype.onClick()
{
alert("Clicked!");
}

Unfortunately at the time my inner function is called, "this" refers
to the google marker that generated the event, and not the
"MyMarkerClass" object that created the function.

How can I reference the "this" of MyMarkerClass, so that it calls into
the proper object?

Many thanks,
Lister
 
L

lister

Nevermind, I sussed it. I just assign "this" to another variable and
let the closure do it's stuff :)

MyMarkerClass.prototype.registerEventHandler()
{
var boundObject = this;
GEvent.addListener(this.GoogleMarker, "click", function()
{
boundObject.onClick();
});

}
 
A

abozhilov

Nevermind, I sussed it. I just assign "this" to another variable and
let the closure do it's stuff :)

MyMarkerClass.prototype.registerEventHandler()
{
   var boundObject = this;
   GEvent.addListener(this.GoogleMarker, "click", function()
   {
       boundObject.onClick();
   });

}

In your design you have circular reference to GoogleMarker from
`boundObject`.
http://en.wikipedia.org/wiki/Circular_reference
 
T

Thomas 'PointedEars' Lahn

lister said:
Hi folks, newbie(ish) here.

No need to tell:
I want to attach an event handler to a google map marker. I want the
event handler to call into a member function of the object that
created it.

eg.

MyMarkerClass.prototype.registerEventHandler()
{
GEvent.addListener(this.GoogleMarker, "click", function()
{
this.onClick();
});
}

MyMarkerClass.prototype.onClick()
{
alert("Clicked!");
}

That's not even working code. Maybe you are using/were looking for

MyMarkerClass.prototype.registerEventHandler(
function() {
GEvent.addListener(this.GoogleMarker, "click",
function() {
this.onClick();
});
}
);

and the like; who knows. Special APIs are off-topic here anyway.

<http://jibbering.com/faq/#posting>


PointedEars
 
L

lister

Well done, lister, for solving your own problem.  And I do like your
explanation of what's happening.

I've seen
    that = this;
used for this purpose.  I like the convention, and use it myself.

Thanks, that's nice and succinct. Will use that. expecially if others
use the same convention.
 
T

Thomas 'PointedEars' Lahn

lister said:
Sorry, I trimmed out the crap for posting and missed off the "=
function()"

Adding the `= function ()' changes the meaning of your code completely; it
turns a /CallExpression/, ultimately produced by an /ExpressionStatement/,
followed by a /Block/ statement into a /FunctionExpression/. Therefore, the
use of scatological metaphors being unwished here notwithstanding, it can
hardly be considered "crap".

Please follow the reference in my previous posting, read the FAQ and FAQ
Notes, and follow the recommendations there. Thank you in advance.


PointedEars
 
S

slebetman

Thanks, I take it this is a problem due to the IE garbage handler bug
I've seen mentioned in my reading?

Any advise on how do clear it? A Java style "finalize()" function to
null the GoogleMarker ref when I'm finished?

Circular reference to non-DOM objects in javascript gets garbage
collected fine in IE. Since your object is called "MyMarkerClass" I
think it's safe to assume that it isn't a DOM object. Just don't
create a circular reference involving a DOM object.
 
T

Thomas 'PointedEars' Lahn

Hans-Georg Michna said:
The original source is, of course, Douglas Crockford. Please see
http://www.crockford.com/javascript/private.html , the
second-last paragraph of the chapter "Private".

I presume closures were well known before Douglas Crockford entered the stage.
He also explains the reason pretty extensively and tells the
whole historic story in one of his lectures (available as Yahoo!
videos), which is an oversight or a mistake in the design of
JavaScript that was never fixed, because Microsoft insisted that
it stay that way, in order not to break existing programs.

Unfortunately, Douglas Crockford has a history of revising
ECMAScript/J(ava)Script history to support his arguments¹, so I dare doubt
this colorful story of his as well (assuming that you did not completely
misunderstand what he was saying).

First of all, Microsoft does not have anything to do with JavaScript nor
could they have influenced the design of JavaScript, Netscape/Mozilla.org's
ECMAScript implementation, which came a few months before the release of
JScript, Microsoft's ECMAScript implementation, or rather their JavaScript
copycat (see the FAQ).

Second, I doubt the meaning of `this' is an oversight or a mistake.
Instead, it appears to be the result of an informed design decision. The
ECMAScript Specification, Edition 3 Final, specifies that `this' is related
to the called execution context and _not_ lexically scoped, and conforming
implementations must comply.

In an information society, doubt everything that you read.


HTH

PointedEars
___________
¹ <http://weblogs.mozillazine.org/roadmap/archives/2008/04/popularity.html#more>
 
T

Thomas 'PointedEars' Lahn

Hans-Georg Michna said:
Yes, the specification says so, but it makes no sense. There is
no good reason why 'this' should be treated differently,

Yes, there is a very simple reason: By contrast, `this' is _not_ an
Identifier, and so it is not subject to scope chain and identifier
resolution. It is a keyword that stands for a specific internal value that
is only set when an execution context is entered. (See also ES3F, sections
10 and 11).
particularly since programs often need 'this' in inner
functions.

I don't follow.
Originally or in the early days they could still have changed it
without breaking too many existing programs, but today it is
difficult to change. I don't want to go into the known history,
as this doesn't help us much now and would only be a waste of
time.
Rubbish.

Douglas Crockford's now widely known workaround is, as I
mentioned:

var that = this;

It is not a workaround. And AFAIK the pattern has not been devised by
Douglas Crockford.

For there to be a workaround, there needs to be a bug first. There is no
bug here; there may be an inconvience for those who have (still) not
understood what `this' is and why it is what it is, but that is their
problem alone.


PointedEars
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
Hans-Georg Michna wrote: [...]
Douglas Crockford's now widely known workaround is, as I
mentioned:

var that = this;
It is not a workaround. And AFAIK the pattern has not been devised by
Douglas Crockford.

For there to be a workaround, there needs to be a bug first. There is no
bug here; there may be an inconvience for those who have (still) not
understood what `this' is and why it is what it is, but that is their
problem alone.

IBTD.

Understanding something in depth does not always make it more
convenient. From what I remember seeing in es-discuss lists, even
language implementors acknowledged the fact that `this` bindings are
unintuitive and inconvenient.

You can see the outcome in infamous Function#bind introduced in ES5
(currently draft).

Non sequitur.


PointedEars
 
J

Jorge

Hans-Georg Michna wrote:
(...)

I don't follow.
(...)

e.g.:

The good:

element.onclick= function (event) {
//'this' points to the element

function useful () {
//can't refer to element as 'this'
//therefore must use 'that'
//'this' points to window
}

//The trick:
var that= this;

useful();
};


The better:

element.onclick= function (event) {
//'this' points to the element

function useful () {
//'this' points to outer 'this'
}

useful();
};

HTH,
 
R

RobG

e.g.:

The good:

element.onclick= function (event) {
  //'this' points to the element

  function useful () {
    //can't refer to element as 'this'
    //therefore must use 'that'
    //'this' points to window
  }

  //The trick:
  var that= this;

  useful();

};

The better:

element.onclick= function (event) {
  //'this' points to the element

  function useful () {
    //'this' points to outer 'this'
  }

  useful();

};

The above would have just as many foibles as the current system - a
function's this keyword would be set differently depending on whether
it was created as function expression or a function declaration.

Consider:

function Foo(name) {
this.name = name;
}

function showNameA() {
alert(this.name);
}

Foo.prototype.name = 'Ooops';
Foo.prototype.showNameA = showNameA;
Foo.prototype.showNameB = function() {
alert(this.name);
};

var fooA = new Foo('A');

fooA.showNameA() // 'Ooops'
fooA.showNameB() // 'A'

Does that seem like an improvement?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top