Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/419.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在构造函数中设置javascript私有变量?_Javascript_Oop_Scope - Fatal编程技术网

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

如何在构造函数中设置javascript私有变量?,javascript,oop,scope,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的所有内部函数?

假设我有一个名为
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
的所有内部函数?

关于javascript中私有和受保护访问的最佳教程如下:


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

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

我最近遇到了一个类似的问题,但我也想使用访问器属性。下面是一个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

我能想到的一种方法是使用一个指定给名称并返回新对象的闭包。您可以通过调用闭包将任何参数传递给构造函数。最终的结果是如下所示:

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

如果您愿意使用ES2015课程

使用ESNext,您可以这样使用:

class-Foo{
#条='';
构造函数(val){
这个#bar=val;
}
其他fn(){
console.log(这个#条);
}
}

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

在ES6+术语中,正确的方法如中所示。然而,如果出于某种原因,您希望坚持使用好的旧构造函数,那么它可以像这样实现

function Foo(val){
  function Construct(){};
  Construct.prototype = { set bar(_){} // you may throw an error here
                        , get bar(){return val;}
                        };
  return new Construct();
};
所以这里发生了两件事

  • 您不会使用接受答案中的属性填充
    Foo
    的实例
  • 与抽象不同,当有人试图通过
    setter
    访问私有变量时,您可以随意抛出错误,也可以不抛出错误
  • 也许您想要实例本身的私有字段,而不是通过原型访问它。那么你可以做你喜欢的事

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

    不管是谁否决了这个,你能解释为什么吗?在我看来这是正确的+1I没有,但在许多语言中,能够使用相同的参数名而不是像“a”这样的名称是很好的。也就是说,拥有一个名为'bar'的参数并将其分配给一个名为'bar'@gabriellamas的变量-我想您不理解这段代码的意义。如果
    bar
    是真正私有的,因此无法从外部访问(这是OP要求的),那么它必须声明为我所做的。而且,如果您像我所做的那样声明
    bar
    ,则无法从原型上定义的方法访问它。您必须在
    bar
    的范围内定义函数。是的,如果要实例化大量的
    Foo()
    对象,那么它就没有那么高效了,但这是一种使bar私有化的方法,这正是我们要问的问题。请删除你的否决票。@Gabriellamas-这种方法没有不好的做法。这只是一种权衡。为了实现隐私,在创建对象时,您会接受一个微小的性能影响。创建对象后,该对象的性能非常好。原型机在那里是为了方便。你没有理由用它来实现你的目标。如果您要创建大量的
    Foo()
    对象,并且性能至关重要,那么这将是一个糟糕的权衡。但是,如果您只是创建了一对,或者此方法的性能非常好,并且您想要可变的隐私,那么此方法是一个很好的实践。@Gabriellamas-此获取隐私的方法不是黑客。它使用该语言支持的特性(闭包)来解决一个不是最初设计到该语言中的问题。这不是黑客攻击-这是一个创造性的解决方案,如果需要它提供的功能,那么使用它绝对没有错。FWIW,你不能拥有真正的私有变量并利用原型。我个人会提供,而不是使代码更复杂…@FelixKing这是怎么回事?+1个很好的例子。有一件事我还很困惑。是什么使
    bar
    in
    var bar=b
    persistent?嗨@Gary,希望我能解释一下:每次构造
    new Foo
    时,都会在该
    Foo
    构造函数的功能范围内创建一个新的
    bar
    。只要
    Foo
    在内存中存在,
    bar
    就会在内存中存在(或者对
    Foo
    中的任何函数的引用,这些函数都可以访问
    bar
    。正如
    Foo
    的每个实例都有自己的
    setBar
    alertBar
    ,它有自己的
    bar
    ,事实上,它也有自己的
    b
    。请参阅这个JSFiddle以获得更简洁的版本:@Gary Javascript区分大小写。Bar和Bar是两个独立的属性。Bar是Foo的私有属性,而Bar是提供对Bar访问的公共属性。这与公认的答案是一样的。我投票赞成这个答案,但后来我意识到它是错误的;每次“fooFactory”调用时,所有原型的方法都是从头开始重新创建的。因此,与直接向对象添加方法相比,它没有任何优势,这只会导致混乱。
    function Foo(val){
      function Construct(){};
      Construct.prototype = { set bar(_){} // you may throw an error here
                            , get bar(){return val;}
                            };
      return new Construct();
    };
    
    function Foo(val){
      Object.defineProperty(this,"bar",{ set: function(){}
                                       , get: function(){return val;}
                                       });
    };