JavaScript - Частное объяснение членов?

Я читаю эту статью из Крокфорда: http://www.crockford.com/javascript/private.html

А в разделе, где он говорит о частном, он говорит:

Частные члены сделаны конструктором. Обычные переменные и параметры конструктора становятся приватными членами.

Теперь, если я сделаю это в моем сценарии:

"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 ?!?

Я могу легко получить доступ к свойству, которое было передано через конструктор! Может кто-нибудь объяснить это лучше, разве эти переменные, передаваемые через конструктор, не должны быть частными?

Спасибо!

4 ответа

Я думаю, что вы неверно истолковали эту информацию. Он не говорит, что частные методы - это те, которые "передаются" через конструктор, он говорит, что это те, которые "сделаны" конструктором.

Чтобы было ясно, посмотрите на это:

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

Это имеет 3 частных переменных. brand,year а также color, Добавив эту строку

this.brand = brand

Вы создаете публичное свойство и присваиваете ему значение из вашей частной переменной. То, что вы назвали публичное свойство и приватную переменную - это одно и то же, ни здесь, ни там, если это прояснит это как

this.publicBrand = brand

Все, что вы назначаете контексту (эта внутренняя функция), является общедоступным. Помните, что контекст является объектом окна, если вы вызываете функцию без нового

"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

Дело не в том, что вы можете получить доступ к значениям, переданным в конструктор. То, что вы сделали, установлено this.brand равно значению, переданному в конструкторе. Поэтому общедоступный brand теперь имеет то же значение, которое было передано. brand внутри конструктора != this.brand пока вы не установите его.

Решение: Использование замыканий для создания недоступной "частной" области.

"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

Внимание: утечка памяти

Это создаст ситуацию, когда сборщик мусора больше не будет очищать память, связанную с экземплярами Class потому что на них всегда будут ссылаться, что приводит к утечке памяти.

Чтобы бороться с этим, мы должны будем вручную удалить ссылку на экземпляры Class, Это можно сделать, добавив один фрагмент кода после parent.setPrivateInstance раздел и один кусок кода после parent.Class.prototype.logName раздел. Эти части кода будут выглядеть так:

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

использование

c = c.deleteFromMemory();

Для примера всех частей, работающих вместе: https://jsfiddle.net/gjtc7ea3/

отказ

Так как это решение вызывает утечку памяти, я бы лично посоветовал не использовать его, если вы не знаете, что делаете, поскольку здесь очень легко совершать ошибки.

Другие вопросы по тегам