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/
отказ
Так как это решение вызывает утечку памяти, я бы лично посоветовал не использовать его, если вы не знаете, что делаете, поскольку здесь очень легко совершать ошибки.