[Answered] Calling object function within object

Comming from a background In python I am findind myself confused when it comes to the avilability of functions declared within an object using constructor notation.

Though this problem is within the “build a random quote generator” it does not specificly apply to it.

I’ve desinged an object to perform some of the tasks I need (just to get object creation down) with buttons calling functions within that object.

For whatever reason I keep getting “this.buildColorScheme() is not a function” whenever my linked button is pressed with an id of “btnGetQuote.”

Am I not understanding the “this” keyword… does javascript have some crazy off shoot OOP thing going on?

function QuoteGenerator(){

    //..
    this.__init__ = function(){

        //..
        this.strQuote = null;
        this.strAuthor= null;

        // ...
        this.txtHeading = document.getElementById('txtHeading'); //..
        this.txtQuote   = document.getElementById('txtQuote'  ); //..
        
        //..
        this.btnTweetQuote  = document.getElementById('btnTweetQuote' ); //..
        this.btnTumbleQuote = document.getElementById('btnTumbleQuote'); //..
        this.btnGetQuote    = document.getElementById('btnGetQuote'   ); //..
        
        //..
        this.btnTweetQuote.onclick  = this.tweetQuote ; //..
        this.btnTumbleQuote.onclick = this.tumbleQuote; //..
        this.btnGetQuote.onclick    = this.getQuote   ; //..
        
        //..
        this.__buildColorScheme__();
    };
    
    // ...
    this.__buildColorScheme__ = function(){
        /* ... */
        
        //..
        clrBgColor = [this.__getRandomNumber__(1,255),this.__getRandomNumber__(1,255),this.__getRandomNumber__(1,255)];
        clrFgColor = [(clrBgColor[0]+80), (clrBgColor[2]+80), (clrBgColor[2]+80)];                    
        
        //..
        for (var item in clrFgColor){if (clrFgColor[item] > 255){clrFgColor[item] = 255;}}
        
        //..
        clrBgColor = "rgb("+clrBgColor.join(',')+")"; //..
        clrFgColor = "rgb("+clrFgColor.join(',')+")"; //..
        
        //..
        document.body.style.backgroundColor = clrBgColor;
        
        //..
        this.btnTweetQuote.style.backgroundColor  = clrBgColor; //..
        this.btnTumbleQuote.style.backgroundColor = clrBgColor; //..
        this.btnGetQuote.style.backgroundColor    = clrBgColor; //..
    };
    
    //...
    this.__getRandomNumber__ = function(start, end){
        /* ... */

        //...
        return Math.floor(Math.random() * (end - start + 1)) + start;
    };
                    
    // ...
    this.getQuote = function(){
        /* ... */
        
        //..
        this.__buildColorScheme__();
    };
                    
    // ...
    this.tweetQuote = function(){
        /* ... */
    };
    
    // ...
    this.tumbleQuote = function(){
        /* ... */
    };

    //..
    this.__init__();
}

//..
var app = new QuoteGenerator();

Yeah, this is a common hangup for developers coming from other languages. this will refer to the call site, not the object in which the code executes. So, in your event handler, this refers to the button you click, not the function it runs. You have two options at this point: 1) Use ES6 arrow functions, which have the lexical scope as you’d expect

this.getQuote = () => {
  //...
}
  1. Use an immediately invoked function expression (IIFE) to cache the lexical scope in a closure

    this.getQuote = (function() {
    var _this = this;
    return function clickHandler() {
    // refer to _this
    }
    })()

1 Like

Wouldn’t _this be (implicitly) declared in the global scope because of the lack of the var keyword before it?

Good catch! I’ve fixed the example.

Before ES6 was #2 the only option as it seems to be researching as such?

I see alternatives such as prototype.bind() which is what I am going with as your answer lead me to find that particular solution. https://codepen.io/braschko/pen/kXGpvY

For the future though I will keep => in mind and encorporate it when more browsers support it.
Thank you for your response!!!