了解公共/私有实例变量

时间:2015-08-05 12:38:13

标签: javascript

我正在阅读关于公共/私人方法的tutorial,并且无法理解差异。

对于私有方法,它说,“私有成员是由构造函数构成的。普通变量和构造函数的参数成为私有成员。”

function Container(param) {
    this.member = param;
    var secret = 3;
    var that = this;
}

对于公共方法,“这种技术通常用于初始化公共实例变量。构造函数的this变量用于向对象添加成员。”

function Container(param) {
    this.member = param;
}

正如您所看到的,这两个函数都有params参数和this.member = param;。一个是私有实例变量,另一个是公共实例变量?

2 个答案:

答案 0 :(得分:0)

了解闭包

打开一个新的函数体会创建一个新的范围。这种范围在JS中称为闭包。在该范围内创建的变量可在其所有子范围中访问。这意味着任何var - 创建的变量都将对子函数可见。在此示例中,myTemporaryVar可在subScope中访问。

function myParentScope() {
  var myTemporaryVar = "sample";

  function subScope() {
    console.log(myTemporaryVar);
  }

  return subScope();
}

使用带有new关键字的函数时,会为当前实例创建一个新的闭包。在该构造函数中创建的任何函数都将保持对范围变量的访问。在下一个示例中,函数sayHi可以访问临时变量myName。

function Person(name) {
  var myName = name;
  this.sayHi = function() {
    console.log("Hi, my name is " + myName + ".");
  };
}

p = new Person("Bob");
p.sayHi(); // Hi, my name is Bob.

实际上,传递的参数与var - 创建的变量相同。构造函数的参数可在任何子函数中访问。所以前面的例子可以简化为:

function Person(name) {
  this.sayHi = function() {
    console.log("Hi, my name is " + name + ".");
  };
}

p = new Person("Bob");
p.sayHi(); // Hi, my name is Bob.

这是JavaScript的一个非常独特的功能,因为它意味着var - 只要仍然有办法访问它们,创建的变量在函数结束后仍然存在。

模拟基于类的OOP隐私

关闭可以被滥用"使用getter和setter函数创建私有成员。

function Person(name) {
  this.getName = function() {
    return name;
  };

  this.setName = function(newname) {
    name = newname;
  };
}

p = new Person("Bob");
console.log(p.getName()); // "Bob"
p.setName("Alice");
console.log(p.getName()); // "Alice"
p.name; // undefined

为什么这不是真正的隐私

必须在构造函数中创建getter和setter才能访问var - 变量。以通用原型扩展方式添加的方法无法访问它们。原型方法也必须使用setter和getter,这使得这些变量的隐私毫无用处。

Person.prototype.sayGoodMorning = function() {
  console.log("Good morning, my name is " + this.getName() + ".");
}

直接访问方法中变量的唯一方法是在构造函数中实际创建它。但是将所有方法放在构造函数中是非常低效的,因为将为每个实例创建方法的新副本。这就是为什么许多人更喜欢使用自定义表示法来识别潜在的私人成员。 Google JavaScript Style Guide建议在变量名末尾添加下划线。

function Person(name) {
  this.name_ = name;
}

Person.prototype.getName = function() {
  return this.name_;
}

Person.prototype.setName = function(name) {
  this.name_ = name;
}

Person.prototype.sayGoodMorning = function() {
  console.log("Good morning, my name is " + this.name_ + ".");
}

程序员有责任不要愚蠢并访问潜在的私人成员。请注意,这与Crockford的观点完全矛盾,但每个观点都是自己的。我在Python之后学习了JS,所以下划线隐私就像是我的第二天性。

答案 1 :(得分:-1)

此变量中没有一个是私有的,因为如果您实例化Container,则可以访问秘密变量:

function Container(param) {
    this.member = param;
    var secret = 3;
    var that = this;
}

var container = new Container();
console.log(container.secret);
container.secret = "toto";
console.log(container.secret);
console.log(container);

结果如下:

Console

正如您所看到的,您可以在没有任何" Getter / Setter"的情况下访问秘密。

如果你想用真正的私有变量做对象javascript,请看本教程:

http://blog.stchur.com/2011/09/26/true-private-variables-in-javascript-with-prototype/