Как установить частные переменные 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