简体   繁体   中英

JavaScript “Class” “Private” Variable Scope

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

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;
}

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