Question

I am surprised that I could not find more on this topic (could be my sub-par search skills). Typically once I think I understand how the JavaScript keyword, "this" works it then stops working the way I understand. I'll address one such issue.

My understanding: "When a function is called using the 'new' keyword ... 'this' refers to the root function/'class'. When used from functions within the instantiated 'class' this refers to the CALLING function". -- This is very important to understand: when the function is called from another function on the page the 'this' keyword will refer calling function and not the 'class' within which the target function lives.

In the following example I have tried two ways to set a variable from a public function. Both fail. I am attempting to understand why this is and how to make this work.

var functionClass = new function(){

    var _isReady = false;

    var _getReady = function(){
        // ... do some work to get ready
        _isReady = true;
    }

    return {

        IsReady: _isReady,
        GetReady: _getReady
    }
}



var functionClass1 = new function () {

    var _isReady = false;
    var _self = this;

    var _getReady = function () {
        // ... do some work to get ready
        _self.IsReady = true;
    }

    return {

        IsReady: _isReady,
        GetReady: _getReady
    }
}


functionClass.GetReady();
functionClass1.GetReady();

console.log(functionClass.IsReady);  // Expect true ... I get false
console.log(functionClass1.IsReady); // Expect true ... I get false

UPDATE:

I Probably should point out that I am using the Revealing Module Pattern and would prefer that any solution be in that context. While I am sure there are a multitude of different ways of doing this I would like to focus the solution to this pattern.

Was it helpful?

Solution 2

When a function is called using the 'new' keyword ... 'this' refers to the root function/'class'

No. It refers to a newly instantiated object that inherits from the object on the constructor functions' prototype property. This object will be the result of the new-expression if none was explicitly returned from the function.

When used from functions within the instantiated 'class' this refers to the CALLING function"

No. It usually refers to the instance.

When the function is called from another function on the page the 'this' keyword will refer calling function and not the 'class' within which the target function lives

No. Again, it usually refers to the instance. Though it always depends on how the function is called - read MDN's introduction to the this keyword.


And in your case, a module creation, you should not use new at all. There is no inheritance involved anywhere. Change it to an immediately-executed function expression (IEFE, you can search for that).

So why do your two attempts fail now?

The functionClass gets assigned an object which has two properties: GetReady which is set to the _getReady function, and IsReady which is set to value of _isReady, i.e. false. Yet, when you call the method, it will only change the _isReady variable, not the IsReady property of functionClass.

In functionClass1 you are correctly assigning to a property. But of what? _self is the this value from the module function that was abused as a constructor, and as explained above that's an object inheriting from another object (whose .constructor is the anonymous function used for the module). It is not - as you seem to have expected - the functionClass1 object which you did return.

So how do you refer to that object correctly? Well, the simplest choice is to use its variable name. Another choice is to use this in the getReady function, which will refer to the object if it called with functionClass.GetReady(). See Javascript: Object Literal reference in own key's function instead of 'this' for pros and cons.

var functionClass = {
    IsReady: false,
    GetReady: function(){
        // ... do some work to get ready
        this.IsReady = true;
    }
};
functionClass.GetReady();
console.log(functionClass.IsReady);  // true now

OTHER TIPS

Try this to see if this is what you need

 var functionClass = (function(){

        var _isReady = false;

        var _getReady = function(){
            // ... do some work to get ready
            _isReady = true;
        }

        return {

            IsReady: _isReady,
            GetReady: _getReady
        }
    })();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top