1

As we know, you can make a "Class" variable "private" in JavaScript by doing the following:

function ClassName(attribute){
    var privateAttribute = attribute;

    this.accessor = function(){
        return privateAttribute;
    }

    this.mutator = function(x){
        privateAttribute = x;
    }
}

I know that this works, and I've used it before. But it kind of breaks down my understanding a tad. Aren't local variables supposed to go out of scope at the end of a function's execution? Shouldn't, according to how JavaScript scope is supposed to work, var privateAttribute be inaccessible by the time you try to call accessor from an instance of ClassName?

https://www.w3schools.com/js/js_scope.asp

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
HumbleWebDev
  • 555
  • 4
  • 20
  • 1
    It remains in scope to members of the object as long as it exists. I'm certain someone will come along with a detailed technical explanation of why that is that I can't articulate right at the moment, but you can be confident that that behavior is well-defined and will remain consistent. – CollinD Jun 15 '17 at 20:57
  • 1
    https://stackoverflow.com/q/500431/215552 Give it a read. – Heretic Monkey Jun 15 '17 at 20:58
  • Possible duplicate of [What is the scope of variables in JavaScript?](https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript) – Heretic Monkey Jun 15 '17 at 21:28

1 Answers1

2

What you are missing is that fact that a function can be called in several ways...

If your function is called as a function, then, yes, when the function ends, all its local data is gone.

But, if the function is called as a "constructor function":

var myObj = new ClassName(data);

Then the function creates an instance of an object, which is stored in the myObj object variable and all the function's private data is available (internally of course) until the object variable goes out of scope.

In addition to this, if a function contains a "closure" (a nested scope that refers to a variable from a higher scope) and that nested function winds up having a longer lifetime than the higher scope where the higher variable came from, then that variable cannot go out of scope even when the function it was defined in does. This concept trips a lot of people up at first, but it makes perfect sense - if a (let's say) returned function relies on data that would normally go out of scope when its block terminates, but the returned function lives longer than this, then the data will not and cannot be garbage collected.

Lastly, and really just to be clear, JavaScript does not actually have classes. It has prototypes and it is these prototypes that an object will inherit from. Because of how prototypes and inheritance work in JavaScript, your example code would really be written with methods being attached to the prototype, so that all instances of the object (created via a constructor function invocation) don't have to store the same function (thus, decreasing the memory footprint of those instances).

function ClassName(attribute){
    // A regular variable will act as a private "class field"
    var privateAttribute = attribute;

    // But members that are attached to 'this' become instance fields
    this.exposedPrivateData = privateAttribute;
}

// Methods get attached to the underlying prototype object that
// all instances of your object will inherit from
ClassName.prototype.accessor = function(){
        return this.exposedPrivateData;
};

ClassName.mutator = function(x){
        this.exposedPrivateData = x;
}
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • @user3496058 Actually, its not messed up at all, but it takes a little getting used to because JavaScript is not like most other languages. JavaScript has "lexical scope" and once you get your head around that, a lot of things become clear. – Scott Marcus Jun 15 '17 at 21:30