了解公共/私有实例变量

2023-11-30

我正在读一本tutorial在公共/私有方法上,无法理解其中的区别。

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

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

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

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

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


了解闭包

打开一个新的函数体会创建一个新的作用域。这种作用域在 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() + ".");
}

在方法中直接访问变量的唯一方法是在构造函数中实际创建它。但是将所有方法放入构造函数中效率极低,因为将为每个实例创建方法的新副本。这就是为什么许多人更喜欢简单地使用自定义符号来识别潜在的私人成员。这谷歌 JavaScript 风格指南建议在变量名称末尾添加下划线。

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_ + ".");
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解公共/私有实例变量 的相关文章