13

i have this class:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }
}

and call it :

    var myobj = new ctest();
    myobj.func1();

isn't supposed that the second alert will popup "huhu" ? func2 is private, can it not access the var1 public variable ?

if a private function cannot access a public variable, how can i do it ?

Thanks in advance!

4
  • 2
    Also, there is not such thing like private here. Commented May 23, 2012 at 11:19
  • This obj.func1() should presumably be myobj.func1() Commented May 23, 2012 at 11:20
  • @forsvarir yeah it should - I fixed it for him. Commented May 23, 2012 at 11:21
  • Read developer.mozilla.org/en/JavaScript/Reference/Operators/this to learn how this works. Commented May 23, 2012 at 11:48

5 Answers 5

17

You need to provide a context for the call to func2:

this.func1 = function() {
    alert(this.var1);
    func2.call(this);
    alert(this.var1);
}

Without the context the call will use the global object (i.e. window) - you should see when you run your current code that window.var1 is getting created between the two alerts.

Sign up to request clarification or add additional context in comments.

10 Comments

if i do what you suggested it says that func2() is not a function
@MIrrorMirror ah, umm, yes - hold on!
That won't work: func2 is a private variable, not a property.
@xdazz fixed now - you have to use .call to add a context to a locally scoped function.
@MIrrorMirror no, the first parameter to .call sets the implicit this value within the function.
|
12

Functions are not tied to instances, therefore your invocation of func2 ends up as invocation without this pointing to the expected instance.

You can either fix the invocation to include the context:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2.call(this);
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }
}

Or you can keep a variable with the wanted object reference around:

function ctest() {
    var that = this;
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        that.var1 = "huhu";
    }
}

2 Comments

can you provide further reading on this topic, as i want to know which is best practise and why
@InsOp I suggest reading the MDN help on the "this" keyword: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
2

Another option is to use Function.bind:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }.bind(this);
}

Note that the browser support for this is not perfect.

2 Comments

Why use that and .bind() at the same time?
@Alnitak: Poor copy and pasting
2

There is no such thing as private in JS, but you can play with scopes using the closures.

Let's say for instance that in your example you don't need to expose var1 as public property. You could easily rewrite your code as the follows:

function ctest() {
    var var1 = "haha";

    this.func1 = function() {
        alert(var1);
        func2();
        alert(var1);
    }

    var func2 = function() {
        var1 = "huhu";
    }
}

Because both func1 and func2 shares the same scope – they are defined in the same function, ctest – they can access to the same variables. Of course in that case you don't have var1 exposed, so: myobj.var1 will be undefined.

If you want var1 to be exposed as property, then what you need is bind func2 to the object instance you created in the constructor:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }.bind(this);
}

Otherwise func2 will have a different context object (this). If the browser doesn't support bind and you don't want use a shim (as shown in the link above), you can take advantage of the closures again:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var context = this;
    var func2 = function() {
        context.var1 = "huhu";
    }
}

IMVHO is less elegant.

Comments

0
function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2(this);
        alert(this.var1);
    }
    var func2 = function(obj) {
        obj.var1 = "huhu";
    }
}

And there is other way to solve this problem, check the other answers :)

1 Comment

@Alnitak But that will not be a problem, obj is parameter.

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.