如何在构造函数中设置javascript私有变量?

时间:2011-07-23 08:01:02

标签: javascript oop scope

假设我有一个名为Foo的javascript函数/类,它有一个名为bar的属性。我希望在实例化类时提供bar的值,例如:

var myFoo = new Foo(5);

会将myFoo.bar设置为5。

如果我将bar设为公共变量,那么这就行了,例如:

function Foo(bar)
{
    this.bar = bar;
}

但如果我想将其设为私有,例如:

function Foo(bar)
{
   var bar;
}

那么我如何设置私有变量bar的值,使其可用于foo的所有内部函数?

7 个答案:

答案 0 :(得分:49)

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")

答案 1 :(得分:20)

您必须将所有需要访问私有变量的函数放在构造函数中:

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 :(得分:4)

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

答案 3 :(得分:2)

我能想到的一种方法是使用分配给名称的闭包并返回一个新对象。您可以通过调用闭包将任何参数传递给构造函数。最终会出现以下情况:

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

答案 4 :(得分:0)

如果您愿意使用ES2015类,

通过ESNext,您可以像这样使用Javascript private variables

class Foo {
  #bar = '';
  constructor(val){
      this.#bar = val;
  }
  otherFn(){
      console.log(this.#bar);
  }
}

在Foo类之外无法访问私有字段#bar。

答案 5 :(得分:0)

在 ES6+ 术语中,执行此操作的正确方法如 @Nitin Jadhav's answer 所示。但是,如果由于某种原因您想坚持使用旧的构造函数,则可以像这样实现;

function Foo(val){
  function Construct(){};
  Construct.prototype = { set bar(_){} // you may throw an error here
                        , get bar(){return val;}
                        };
  return new Construct();
};

这里发生了两件事。

  1. 您没有使用已接受答案中的属性填充 Foo 的实例。
  2. Private Class Fields 抽象不同,当有人试图通过 setter 访问私有变量时,您可以自由地抛出或不抛出错误。

也许您想要实例本身的私有字段,而不是通过原型访问它。那么你可能会喜欢;

function Foo(val){
  Object.defineProperty(this,"bar",{ set: function(){}
                                   , get: function(){return val;}
                                   });
};

答案 6 :(得分:-2)

我最近遇到了类似的问题,但也希望使用访问者属性。下面是一个基于我想出的解决方案的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