带有私有变量的JavaScript构造函数模式

JavaScript constructor pattern with private variables

本文关键字:构造函数 模式 JavaScript 变量      更新时间:2023-09-26

我知道在JS:中模拟私有变量是可能的

function ConstructorPattern() {
  var privateVar = 'hi there';
  this.getVar = function() {
    return privateVar;
  };
};

但根据Learning JavaScript Design Patterns,当引用类Car和方法toString:的一些类似代码时

上面是构造函数模式的一个简单版本,但它确实存在一些问题。一个是它使继承变得困难,另一个是为使用Car构造函数创建的每个新对象重新定义toString()等函数。这不是很理想,因为理想情况下,该功能应该在Car类型的所有实例之间共享。

因此,在我的案例中给出的解决方案是通过原型添加getVar函数:

ConstructorPattern.prototype.getVar = function() {
  return privateVar;
};

当然,这个函数不知道privateVar是什么,所以它不起作用。我知道模块模式,但我特别希望能够实例化多个实例。

有没有什么方法可以在原型中"正确"使用构造函数模式,同时仍然获得"私有"功能?

EDIT:如果没有办法做到这一点,那么为每个类实例重新定义方法真的那么糟糕吗?我最近开始研究采用这种方法的代码库。好像我唯一错过的就是继承?

第2版:根据接受答案中的链接标记为重复。

有没有什么方法可以在原型中"正确"使用构造函数模式,同时仍然获得"私有"功能?

没有。这种具有特权函数的模式基于闭包范围,不能与共享函数一起使用。所有特权方法都必须是特定于实例的。

如果没有办法做到这一点,那么为每个类实例重新定义方法真的那么糟糕吗?

没有。现代JavaScript引擎非常好地优化了这种模式。当然,有一点开销,但在典型的设置中你不会注意到。

好像我唯一错过的就是继承?

继承仍然是可能的,请参阅JAVASCRIPT模块模式中的定义私有字段成员和继承。当然,派生子类不能直接访问在父构造函数中声明的私有变量,但通常它们不需要直接访问。

当您在对象的原型上创建getVar时,当您执行以下操作时,它不会被调用:

objectName.getVar();

因为原型的方法来自AFTER对象方法。下面的例子将向您展示我的意思:

function Car() {
  var privy = "hidden";
  this.getPrivy = function() {
    return privy; 
  }
}
Car.prototype = {};
Car.prototype.getPrivy = function() {
  return 'i came from prototype'; 
}
var obj = new Car;
obj.getPrivy();

JS遵循如下调用链:对象方法->原型方法->原型原型方法等等…一直返回到Object.prototype。当找到有效方法时,它会停止并返回。在您的案例中,实例的方法先于原型的方法。