带有私有变量的JavaScript构造函数模式[重复]

Posted

技术标签:

【中文标题】带有私有变量的JavaScript构造函数模式[重复]【英文标题】:JavaScript constructor pattern with private variables [duplicate] 【发布时间】:2014-11-10 14:49:12 【问题描述】:

我知道在 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 是什么,所以它不起作用。我知道module pattern,但我特别希望能够实例化多个实例。

有什么方法可以“正确”地使用原型的构造函数模式,同时仍然获得“私有”功能?

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

EDIT2:根据已接受答案中的链接标记为重复项。

【问题讨论】:

不使用构造函数模式(没有一些技巧,我不鼓励)。但是,您可以通过使用 Object.defineProperty(); 来实现隐私的“形式”;使您的属性不可枚举,不可写,不可配置。否则模块模式是要走的路。 回答您的编辑,如果您要在每个实例上重新定义您的方法,为什么要使用构造函数? 它们使用相同的方法,但是为每个实例化的对象创建一个新的方法实例。上面的构造函数模式链接中对此进行了解释。 实际上,为了清楚起见,您不是在创建方法的新实例,而是在对象的原型链中添加方法。我添加了一个带有解释的答案 嗯,不。 “私有”属性是通过使用局部变量来模拟的。变量受词法范围的约束。并且原型函数是在这些私有变量的词法范围之外定义的。 【参考方案1】:

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

objectName.getVar();

因为原型的方法出现在对象方法之后。下面的示例将向您展示我的意思:

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。当找到有效方法时,它会停止并返回。在您的情况下,您的实例方法位于原型方法之前。

【讨论】:

这似乎根本无法回答问题。 这不是对最初问题的回答,而是对主要问题中的一个 cmets 的回答。 ;) 唯一不属于你(或我)的评论是 “他们使用相同的方法,但是为每个实例化的对象创建一个新的方法实例。在上面的构造函数模式链接。”。而且我看不出这与您发布的内容有何关系。您发布的内容似乎更像是评论而不是答案。 是的,但这种说法显然是一种误解,所以我选择阐明一些观点。 (你说得对,这不是一个明确的问题)。 我不认为 OP 在这里误解了什么,但我可能是错的。【参考方案2】:

有什么方法可以“正确”地使用原型的构造函数模式,同时仍然获得“私有”功能?

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

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

没有。现代 JavaScript 引擎很好地优化了这种模式。当然,有 a little overhead,但在典型设置中您不会注意到。

似乎我唯一错过的就是继承?

仍然可以继承,请参阅Define Private field Members and Inheritance in JAVASCRIPT module pattern。当然,派生子类不能直接访问在父构造函数中声明的私有变量,但通常它们也不需要。

【讨论】:

以上是关于带有私有变量的JavaScript构造函数模式[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Javascript的私有变量和方法共有变量和方法以及特权方法构造器静态共有属性和静态共有方法

详谈单例饿汉和懒汉模式

设计模式

带参数的Java私有构造函数[重复]

java中私有构造函数的作用

带有私有构造函数的类型的JsonSerializationException