0

I want to create the following JavaScript object:

function Thumbnail(thumbnailUrl) {
    this.thumbnailUrl = thumbnailUrl;
    this.width = 200;
    this.height = 150;
    this.element = init(this.width, this.height, this.thumbnailUrl);
    this.element.addEventListener("mouseover",this.onmouseover);

    function init(width, height, thumbnailUrl) {
        var thumbViewHTML  = "<div class='container shadow' style='width:"+width+"px; height:"+height+"px; background: green;'>";
        thumbViewHTML += "<div class='container' style='width:100%; height:80%; background: yellow'>";
        thumbViewHTML += "<img class='centered' src='"+thumbnailUrl+"'  style = 'max-width: 100%; max-height: 100%;'/>";
        thumbViewHTML += "</div>";
        thumbViewHTML += "<div class='container' style='width: 100%; height:20%; background: black'>";
        thumbViewHTML += "<div class='textStyle centeredVertically' style='margin-left:5px; color: white'>Landscape</div>";
        thumbViewHTML += "</div>";
        thumbViewHTML += "</div>";

        return DOMElementFromHtml(thumbViewHTML);
    }

    return this;
}

Thumbnail.prototype.onmouseover = function() {
    console.log(this.width); //undefined with this pointing to this.element property on the Thumbnail object
}

function DOMElementFromHtml(htmlString) {
    var tempDiv = document.createElement('div');
    tempDiv.innerHTML = htmlString;
    return tempDiv.firstChild;
}

When I access this.width on the onmouseover handler I get undefined because this points to the this.element member of the Thumbnail object. Is there any way to get this inside that method to point to the Thumbnail instance instead of the this.element instance.

I assume I could implement onmouseover in the local scope of the Thumbnail constructor and that might work but what if I want onmouseover to be a public method that can be modified externally?

Flimzy
  • 60,850
  • 13
  • 104
  • 147
Horatiu Paraschiv
  • 1,630
  • 2
  • 15
  • 37

1 Answers1

0

Bind the function to this like so:

this.element.addEventListener("mouseover",this.onmouseover.bind(this));

Although you had this.onmouseover, as you don't call it right there, but (need to) pass a function reference, the actual call (when the event triggers) is not made with the this. prefix, and so it will be called without a specific context. Depending on whether you are in non-strict or strict mode, this will then refer to the global object or be undefined.

This behaviour you can override with bind, which creates a new function, but which will be ensured to have as context the argument you pass to it.

You can read more about the subject at "How does the this keyword work?"

Community
  • 1
  • 1
trincot
  • 211,288
  • 25
  • 175
  • 211
  • Great that does work, thanks. I am a pretty experienced OOP dev but JavaScript is a different kind of beast in that regard :). – Horatiu Paraschiv Mar 29 '17 at 23:33
  • Yes, it is confusing. Some have suggested to program without the `this` keyword as it regularly leads to undesired "surprises", while others embrace it. – trincot Mar 29 '17 at 23:35