Heres a bit of cleaned up code from a picture gallery im writing to learn js. I create the gallery as an object but at some point i lose track of what "this" points to. It doesnt make sense to me what happens at the bottom (look at the comments). Can someone please explain?
function Gallery(parentID)
{
// ...
this.showDiv = document.createElement("div");
// ...
this.show = function ()
{
document.body.appendChild(this.showDiv); //will be given css absolute position to "pop up"
this.showDiv.innerHTML = '<img class="displayImage" src="' + this.picList[this.showIndex] + '">'; //fill with image
this.showDiv.focus();
this.showDiv.onclick = this.hide;
}
this.hide = function ()
{
alert(this.innerHTML); // <= WHY DOES THIS SHOW THE INNERHTML CONTENTS OF this.showDiv??????
//alert(this.showDiv.innerHTML); // <= shouldnt this be correct?
this.parentNode.removeChild(this); //doesnt work
}
}
Let me know if i cleaned up some code that might have affected the results and ill fill it in.
Thanks.
This line is the problem. It doesn’t work like in Python;
this.hide
is not a bound method. It’s just thehide
function, not bound to any particularthis
.One way to fix it is:
But the
.bind()
method of functions is a rather new standard; it isn’t in all old browsers. So you might want to roll your own instead:(Generally
this
is kind of strangely behaved in JavaScript; the main thing to remember is thatthis
always refers to the innermost function’sthis
, which could be whatever the caller wants it to be. Sometimes you see JS code do things likevar self = this;
to give a particular function’sthis
a name that can be used in nested functions; in Python, of course, that is just sort of the way things work automatically.)This refers to the object that called the function. So when you say
this.showDiv.onclick
, showDiv is what is calling the function. Thereforethis.innerHTML
actually meansthis.showDiv.innerHTML
If you insist on using a constructor function, rather than a factory, then keep
this
in mind --If you have a method (or any function you call as a method, and not as a constructor), and that method references
this
, thatthis
statement gets resolved at the instant the function is called rather than when it is defined.In a strict class-based language, there'd be all kinds of errors, here.
But through the magic of late-binding (deciding what
this
means at the last possible second, during execution), it goes off without a hitch.There is one hitch, however: Functions inside of functions. You want
this
to point to thethis
of the outer method. It doesn't. In old (current) JS, it points atwindow
. In future JS, it points at nothing.Assuming Bob has both a name and an age, now, you can assign the function like last time, and it will work. The function will see that
bob
was in front of the dot, and thus the subject ofthis
(note: not really how it works, but how it appears to work, one function deep).outerThis
will save the reference for the inner function to use.Another option is:
call
is a method that functions have (did I mention that functions are objects), which lets you specifythis
for that particular execution, rather than giving another object a method (a reference, really).bind
works just likecall
, except it returns a function where thethis
is permanently set to value you passed in. Andbind
isn't in OldIE.One other major point of reference: When you use event-listeners,
this
points to the element you put the listener on.You can delegate listeners (attaching one listener to a
<ul>
, that listens for any click on any of its<li>
, for example. In that instance,this
would be the<ul>
, because it would be the object which the listener was attached to, when it was triggered.Hope that makes things a little clearer.