Как установить частные переменные javascript в конструкторе?
Скажем, что у меня есть функция/класс javascript под названием Foo
, и у нее есть свойство, называемое bar
. Я хочу, чтобы значение bar
предоставлялось при создании экземпляра класса, например:
var myFoo = new Foo(5);
установит myFoo.bar
в 5.
Если я делаю bar
общедоступную переменную, то это работает, например:
function Foo(bar)
{
this.bar = bar;
}
Но если я хочу сделать его приватным, например:
function Foo(bar)
{
var bar;
}
Тогда как бы установить значение частной переменной bar
таким образом, чтобы она была доступна для всех внутренних функций Foo
?
Ответы
Ответ 1
Вы должны поместить все функции, которые должны получить доступ к частной переменной внутри конструктора:
function Foo(bar)
{
//bar is inside a closure now, only these functions can access it
this.setBar = function() {bar = 5;}
this.getBar = function() {return bar;}
//Other functions
}
var myFoo = new Foo(5);
myFoo.bar; //Undefined, cannot access variable closure
myFoo.getBar(); //Works, returns 5
Ответ 2
Одно из лучших учебных пособий по частному и защищенному доступу в javascript: http://javascript.crockford.com/private.html.
function Foo(a) {
var bar = a; // private instance data
this.getBar = function() {return(bar);} // methods with access to private variable
this.setBar = function(a) {bar = a;}
}
var x = new Foo(3);
var y = x.getBar(); // 3
x.setBar(12);
var z = x.bar; // not allowed (x has no public property named "bar")
Ответ 3
function Foo(b)
{
var bar = b;
this.setBar = function(x){
bar = x;
}
this.alertBar = function(){
alert(bar);
}
}
var test = new Foo(10);
alert(test.bar); // Alerts undefined
test.alertBar(); // Alerts 10
Ответ 4
Один из способов, который я могу придумать, - использовать закрытие, которое присваивается имени и возвращает новый объект. Вы должны передать любые аргументы конструктору через вызов замыкания. Это будет выглядеть примерно так:
var fooFactory = function (a, b) {
var c = 5,
d = 6,
foo;
foo = function (a, b) {
this.a = a;
this.b = b;
this.bar();
}
foo.prototype.bar = function () {
//do something with c and d
this.c = c + d;
}
foo.prototype.getC = function () {
return c;
}
foo.prototype.getD = function () {
return d;
}
return new foo(a, b);
};
Таким образом, a и b всегда объявляются однозначно. Затем вы создадите свой объект следующим образом:
var obj = fooFactory(1, 2);
//obj contains new object: { a: 1, b: 2, c: 11 }
console.log(obj.getC());
//returns 5
Ответ 5
Если вы хотите использовать классы ES2015,
с ESNext вы можете использовать закрытые переменные Javascript, например:
class Foo {
#bar = '';
constructor(val){
this.#bar = val;
}
otherFn(){
console.log(this.#bar);
}
}
Закрытое поле #bar недоступно за пределами класса Foo.
Ответ 6
Я разработал модуль, который помогает вам использовать ограничение доступа в классе JavaScript под названием Capsulable. (Частный и защищенный статический)
Если вы заинтересованы, проверьте пакет ниже. https://github.com/hmmhmmhm/capsulable
const Capsulable = require('capsulable')
const Field = Capsulable()
class A {
constructor(_field){
// Configure data fields.
Field(this, _field)
// The code below provides access to
// the data fields when creating
// functions within the class.
Field(this).private
Field(this).protected
Field(this).protectedStatic
}
}
module.exports = A
Ответ 7
Недавно у меня была аналогичная проблема, но я также хотел использовать свойства accessor. Ниже приведен пример Foo (Bar), основанный на том, что я придумал для решения. Этот пример тривиален, но его можно легко расширить с помощью более сложных функций get/set.
function Foo(Bar){
Object.defineProperty(this,"bar",{get:function(){return Bar},set:function(val){Bar=val}});
}
x=new Foo(3);
y=x.bar; //3
x.bar++; //x.bar==4