简体   繁体   中英

JavaScript - Private members explanation?

Im reading this article from Crockford: http://www.crockford.com/javascript/private.html

And in the section where he talks about Private, he says:

Private members are made by the constructor. Ordinary vars and parameters of the constructor becomes the private members.

Now if I do this in my script:

"use strict"
function car(brand) {
    this.brand = brand;
    var year = 2012;
    var color = "Red";
}

var bmw = new car("BMW");
console.log(bmw.brand); // BMW -> VISIBLE ?!?

I can easily access property that was passed through constructor! Can someone explain this better, shouldn't these variables passed through constructor be private?

Thanks!

I think you've mis-interpreted that bit of information. It doesnt say that private methods are those that are "passed through" the constructor, it says its those that are "made by" the constructor.

To be clear, look at this:

function car(brand) {
    var year = 2012;
    var color = "Red";
}

That has 3 private variables. brand , year and color . By adding this line

this.brand = brand

You are creating a public property and assigning it the value from your private variable. That you've named the public property and the private variable the same thing is neither here nor there, if it makes it clearer think of it as

this.publicBrand = brand

It's not that you can access values passed into the constructor. What you've done is set this.brand equal to the value passed in the constructor. Therefore, the publicly available brand now has the same value that was passed in. The local brand inside the constructor != this.brand until you set it.

Everything you assign to the context ( this inside function) is public available. Be aware that the context is the window object if you call the function without new

"use strict"
function car(brand) {
    this.brand = brand; //Public (can be accessed from outside because it is attached to the context/this)
    var year = 2012; //Private (inside function only)
    var color = "Red"; //Private (inside function only)
}

var bmw = new car("BMW");
console.log(bmw.brand); // BMW -> VISIBLE -> this.brand = brans

Solution: Using closures to create a inaccessable "private" scope.

"use strict";

(function (parent) {
    (function (parent) {
        var instances = {};

        parent.getPrivateInstance = function (c) {
            return instances[c];
        };

        parent.setPrivateInstance = function (c, value) {
            instances[c] = value;
        };
    } (this));

    parent.Class = function (name) {
        setPrivateInstance(this, {
            name: name
        });
    };

    parent.Class.prototype.logName = function () {
        console.log(getPrivateInstance(this).name);
    };
})(window);

var c = new Class("test");

c.logName(); // "test"

console.log(c.name); // undefined

Caution: Memory leak

This will create a situation wherein the garbage collector will no longer clear the memory associated with the instances of Class because it they will always be referenced, which results in a memory leak.

To combat this we'll have to manually remove the reference made to the instances of Class . This can be done by adding one piece of code after the parent.setPrivateInstance section and one piece of code after the parent.Class.prototype.logName section. Those pieces of code would look like this:

parent.deleteFromMemory = function (c) {
    delete instances[c];
};
parent.Class.prototype.deleteFromMemory = function () {
    deleteFromMemory(c);
};

Usage

c = c.deleteFromMemory();

For a example of all the pieces working together: https://jsfiddle.net/gjtc7ea3/

Disclaimer

As this solution causes a memory leak I would personally advice against using it unless you know what you are doing, as it is very easy to make mistakes here.

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