简体   繁体   中英

How to access private variable using a public method within same object in javascript?

I am trying to understand Encapsulation through this link

 function Test() { var prop1 = "one"; this.prop2 = "two"; function meth1() { console.log("Inside meth1" + prop1); } this.meth2 = function() { console.log(this.prop2 + "................, " + meth1()); }; this.meth4 = function(val) { prop1 = val; console.log("inside meth4" + prop1); } } var tc = new Test(); var result1 = tc.meth2(); var result3 = tc.prop1; 

According to the link meth1() accessed through this.meth2 should work, but to my surprise i got undefined.

Could you please shed some light on what is happening here. I am using IE 9 for this and getting

LOG: Inside meth1one 
LOG: two................, undefined 

The code in Rajesh's answer is great but I would like to add a couple words about encapsulation in JavaScript and the behaviour of "this".

First of all, in my example I won't be using 'new' as it is evil. 'new' forces you to use this inside the function and its behaviour isn't really transparent. Your code itself and the usage of scope will be much easier to understand without it.

There are two important facts about referring to different variables inside the code:

1) 'this' points to the object inside which it is used. This can lead to confusion as functions are first-class objects but 'this' inside your subfunctions points to the parent function (Test()). Don't use 'this' inside functions to avoid confusion, use it inside objects.

2) JavaScript has function scope and this is how encapsulation basically works. Inner functions can see variables declared in outer objects. Re-declaring variables inside an inner function with the same name overwrites the outer variable instead of creating an inner copy with higher precedence.

If you build your code without using 'new' and 'this' inside functions, your question should be self-explanatory:

function build_test_object() {

    //This object will house all the functionality we will need to return
    var that = {};

    //This is a variable visible only while executing build_test_object
    var prop1 = "one";

    //display_prop1 is a function that is visible only inside build_test_object
    //This way it will be protected after you use build_test_object: the function itself cannot be changed even if the object is altered
    var display_prop1 = function () {
        window.alert(prop1);
    }

    //And now we assign this function to the object we will return.
    that.disp_prop = display_prop1;

    //Returning the finished object
    return that;
}

//Create the object
var test_object = build_test_object();
//Display the property
test_object.disp_prop();

Note how prop1 and display_prop1 cannot be changed from outside the build_test_object code. Even if test_object.disp_prop is replaced, they will remain intact (this is important if other methods inside build_test_object use prop1 or display_prop1). This is known as a closure: build_test_object() has already resolved and whatever was inside its function scope without being exposed is immutable.

For a comprehensive explanation of scope, closures and proper encapsulation methods in JavaScript I recomment "JavaScript: The Good Parts" by Douglas Crockford as this is a bit beyond the scope of one question on this site.

in addition to @Michael's answer, when you try to make a function as a class, remember to return value. This value will be publicly available. In a class structure, var result3 = tc.prop1; should return undefined . Only way to access it should be a function. Following is a representation

 function Test() { // To hold context as object inside functions var self = this; self.prop1 = "one"; self.prop2 = "two"; // method to access prop1 function meth1() { return self.prop1; } // method to access prop2 function meth2() { return self.prop2; }; // Properties that will be publically available. // Never add private variables here. return{ "meth1":meth1, "meth2":meth2 } } var tc = new Test(); var result1 = tc.meth1(); // Should be "one" var result2 = tc.prop1; // Should be "undefined". Private property var result3 = tc.meth2(); // Should be "two" console.log(result1,result2,result3) 

You are successfully calling meth1() from inside this.meth2() . That's where you are seeing the Inside meth1one message displayed by the console.log() inside meth1() .

The undefined value you see on the next line of the log is simply because you are trying to display the value returned by meth1() , but meth1() does not return a value! Therefore its return value is undefined , as displayed by the console.log() in this.meth2() .

Debugging Tip

I suggest stepping through your code in the JavaScript debugger instead of just relying on console.log() . Single step into each function and each line of code. This will help you understand the flow of control in the code.

To make this easier, write your functions on multiple lines instead of making them one-liners, eg:

function meth1() {
    console.log( "Inside meth1" + prop1 );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM