Javascript OOP public and private variable scope

I've got a question regarding public and private variables in a Javascript object. Here's the simple code I've been playing with to get my head around variable scope as well as private and public properties.

var fred = new Object01("Fred");
var global = "Spoon!";

function Object01(oName) {
    var myName = oName;
    this.myName = "I'm not telling!";
    var sub = new subObject("underWorld");
    this.sub = new subObject("Sewer!");

    Object01.prototype.revealName = function() {
        return "OK, OK, my name is: " + myName + ", oh and we say " + global;
    }

    Object01.prototype.revealSecretName = function() {
        console.log ("Private: ");
        sub.revealName();
        console.log("Public: ");
        this.sub.revealName();
    }
}

function subObject(oName) {
    var myName = oName;
    this.myName = "My Secret SubName!";

    subObject.prototype.revealName  = function() {
        console.info("My Property Name is: " + this.myName);
        console.info("OK, my real name is: " + myName + ", yeah and we also say: " + global);
    }
}

The funny thing I've observed so far is within my objects, a plain var is treated as private (obviously, since they are in a function block), and a this version is public. But I've noticed that the a variable with the same name with this.xxx seems to be considered a different variable. So, in the example above, my object fred will report something different for this.myName compared with my function to pull my var myName.

But this same behavior isn't the same for a sub-object I create. In the case of var sub vs this.sub both above use a new subObject call to supposedly make two subObjects. But it seems both this.sub and var sub return the Sewer! version.

Som I'm a bit confused about why if I use Strings for this.myName and var myName I get two different results, but my attempt to do the same with another object doesn't produce a similar result? I guess it could be that I'm using them wrong, or not understanding the differences between a this and var version.

Answers


Your biggest problem here isn't actually the difference between this-based object properties and var-declared variables.

Your problem is that you're trying to make prototype act as a wrapper that will give you protected class properties which are available to sub-classes, let alone instances of your main class.

prototype can not work on "private" members of a class at all (that being the variables defined within the scope of the constructor function, rather than being properties added to the constructed object you're returning).

function Person (personName) {
    var scoped_name = personName;

    this.name = "Imposter " + scoped_name;
}


Person.prototype.greet = function () { console.log("Hi, I'm " + this.name + "!"); };


var bob = new Person("Bob");
bob.greet(); // "Hi, I'm Imposter Bob!"

The point of the prototype string is either to provide methods which operate on the publicly-accessible properties of your objects (like if you wanted to change the value of this.name, but you'd forever lose the hidden scoped_name reference)...

...or if you want ALL of the same kind of object to have access to the SAME value.

function Student (name, id) {
    function showIDCard () { return id; }
    function greet () { console.log("I'm " + name + ", and I attend " + this.school); }

    this.showID = showIDCard;
    this.greet = greet;
}


Student.prototype.school = "The JS Academy of Hard-Knocks";
Student.prototype.comment_on_school = function (feeling) {
    console.log("I " + feeling + " " + this.school);
}

var bob = new Student("Bob", 1);
var doug = new Student("Doug", 2);
var mary = new Student("Mary", 1);


mary.school = "The JS School of Closure";



bob.greet(); // I'm Bob and I attend The JS School of Hard-Knocks
mary.greet(); // I'm Mary and I attend the JS School of Closure
mary.comment_on_school("love"); // I love The JS School of Closure

prototype has defined a default value for school, for Students who aren't given their own. prototype also provided functions which can be shared between objects, because the functions use this to access the actual properties of the object.

Any internal variables of the function can ONLY be accessed by properties or methods which are defined INSIDE of the function.

So in this case, the prototype methods can NEVER access id, except through this.showID, because this.showID is a reference to the showIDCard function, which is created for each and every single student, who has their own unique id, and their own copy of that function has a reference to their own unique copy of that argument.

My suggestion for applying large-scale "class" methodology to JS is to go with a style which favours composition of objects. If you're going to sub-class, make each sub-class a module, with its own public-facing interface, and its own privately-scoped vars, and then make that module the property of whatever you were trying to make, rather than trying to get chains of inheritance working.

That is way, way too much work in JS, if you're anticipating doing something like inheriting from a base-class, and then extending it 8 or 10 generations. It will just end in tears, and complaints that JS isn't "OOP" (in the style you'd like it to be).


There's no private or public, there's variables and object properties.

Variables and object properties are different in many more ways than the one of variables having a variable scope and object properties not having a variable scope. Variable scope is not the same as private property of an object, because it's not a property but a variable.

Variables do not belong to any object but they can be sustained through closures. You can invoke those closures as a property of any object or without any object at all and the supposed private properties will work:

function A() {
    var private = 0;

    this.setPrivate = function( value ) {
        private = value;    
    };

    this.getPrivate = function() {
        return private;
    };
}

var a = new A();

a.getPrivate() //0;

var b = [];

b.fn = a.setPrivate; //The function is fully promiscuous, especially since the data is closed over by it,
                    //so it doesn't matter at all where or how it's invoked.

b.fn(1);

a.getPrivate(); //1

You are redefining functions in a prototype object every time the constructor is called. The whole point of prototypes is that you only have to create certain function objects just once. You are assigning methods to the prototype object inside a function, so every time that function is called, the functions are recreated and form new closures that refer to specific state.

I showed above that closures, because they hold state in the closed over variables, don't care about how they are invoked. So when you assign a closure as a property to the prototype, all the instances you have refer to the latest closure assigned, and you are getting its state.

I recommend using the standard way of defining "classes" in JS and not mixing it up with closures:

function A() {
    this._private = 1;
}
//Note, this code is outside any function
//The functions assigned to prototype are therefore only defined once.
A.prototype.getPrivate = function() {
    return this._private;
};

A.prototype.setPrivate = function( value ) {
    this._private = value;
};

var a = new A();

You can find a good tutorial here: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Details_of_the_Object_Model


Need Your Help

android apk's silent installation

android apk silent-installer

I'm searching for a way to program my application to install silently an apk file.