0

lick() is a private method of Cat. Unfortunately, Cat's this.paw is not accessible in lick(). Is there a simple way to create a private method that has access to the member variables of its containing class?

<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p id="catStatus">???</p>
<script>
function Cat() {

    this.paw;

    var lick = function() {
        alert(this.paw);
        if(this.paw == "sticky") {
            alert("meow");
            document.getElementById("catStatus").innerHTML = "*Slurp*";
        }
    };

    this.beCat = function() {
        this.paw = "sticky";
        lick();
    }
}
var kitty = new Cat();
kitty.beCat();
</script>
</body>
</html>

Result

3 Answers 3

2

The value of this depends on how you call the method.
Since you're not calling the method on the object instance, this becomes the global object.

Instead, you need to save this in a variable:

function Cat() {
    this.paw = ...;

    var me = this;

    var lick = function() {
        alert(me.paw);
        if(me.paw == "sticky") {
            alert("meow");
            document.getElementById("catStatus").innerHTML = "*Slurp*";
        }
    };

    this.beCat = function() {
        this.paw = "sticky";
        lick();
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Actually, this does not refer to the global object within lick(), it refers to the lick function itself.
Honest question: why did you add ellipsis to the declaration of this.paw? Declaring this.paw without a value prevents an exception when referencing the variable. this.paw = ...; produces a syntax error. Maybe I should use this.paw = undefined; instead.
@andersand It would make since to me that this would refer to lick inside lick, but if you alert(this.toString()) inside lick, it actually says "[object Window]", which is the same thing it says in a <script> tag outside any function so I think that's the global object. Inside beCat on the other hand, it says "[object Object]". I think this is because lick has not been instantiated with new. (I only tried this in Firefox.)
1

There are a couple ways to solve this. The problem is that the context inside of lick is not the instance of cat. You can either:

Use the call method to set the context

this.beCat = function() {
    this.paw = "sticky";
    lick.call(this);
};

or use closure

var instance = this;
var lick = function() {
    alert(instance.paw);
    if(instance.paw == "sticky") {
        alert("meow");
        document.getElementById("catStatus").innerHTML = "*Slurp*";
    }
};

2 Comments

Is that really a closure? It doesn't seem to me to resemble this description of a closure. But I'm really not sure.
Sure it is, it's a closure over the variable instance inside the function lick.
1

The context of this depends upon who called the function. In this case it is beCat. You can however explicitly specify the this scope by using call.

In your case:

    this.beCat = function () {
        this.paw = "sticky";
        lick.call(this);
    }

Or you can store the this in a variable.

You can read more about the this scope/how it works here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.