当前位置: 首页 > 知识库问答 >
问题:

javascript - 为什么 MDN 说原型继承中不能有私有属性?

壤驷承
2023-09-30

MDN 说私有属性是原型继承中没有简单替代方案的特性:

image.png

可是不是能用闭包写私有属性吗:

function C() {  // 私有属性  let value = 0;  Object.defineProperty(this, "v", {    get: () => value,    set: (v: number) => value = v,  });}

es6 类写法:

class C2 {  #value = 0;  get v() {    return this.#value;  }  set v(v) {    this.#value = v;  }}

这两种写法有什么区别吗?

共有2个答案

鲁单弓
2023-09-30

MDN 的作者措辞还是非常严谨的,“简单替代方案”,也就是说实现类似的功能,道路将会非常曲折。
你的方法已经略显曲折了,但还是没有完全模拟出私有属性该有的样子——如果使用原型链继承的话,所有子类实例的 .v 属性都会指向同一个 value

function SubC (){}SubC.prototype = new C();var subC1 = new SubC();var subC2 = new SubC();// 注意这里修改的是 subC1.vsubC1.v = 10086;// 注意这里打印的是“没被修改”的 subC2.vconsole.log(subC2.v) // 10086

不过,这并不是你的写法有问题,而是原型链继承的固有缺陷,所以这里要被迫使用构造函数继承,这就偏离了“原型链继承”的语境限制,复杂程度也更上一层楼:

function SubC1 (){  C.call(this);}SubC.prototype = new C();
段干麒
2023-09-30

MDN 文档中关于原型继承中不能有私有属性的说法并不准确。实际上,JavaScript 中的类(自 ES6 引入)提供了私有属性的特性。这主要是通过 # 前缀来达成的,它表示一个属性是私有的,即只能在类的内部访问。

在你提供的例子中,C2 类的 #value 就是一个私有属性。只有在 C2 内部,或者继承自 C2 的类中,才能访问到这个属性。从外部是无法直接访问这个属性的,尝试访问会抛出一个错误。

而你的第一个例子中,value 并不是真正的私有属性。它只是一个用 getter 和 setter 方法模拟的私有属性。这种方法并不能阻止外部代码直接访问或修改这个属性。例如,如果我知道这个 getter 和 setter 的实现,我可以直接调用 Object.defineProperty 来修改或删除这个属性。

因此,虽然 JavaScript 的原型继承中确实不支持真正的私有属性,但 ES6 类提供了私有属性的特性,这是一个很重要的区别。这种特性可以提供更好的封装性和安全性,是面向对象编程的一个重要特性。

 类似资料:
  • FAQs in section [24]: [24.1] 如何表示“私有继承”? [24.2] 私有继承和组合(composition)有什么类似? [24.3] 我应该选谁:组合还是私有继承? [24.4] 从私有继承类到父类需要指针类型转换吗? [24.5] 保护继承和私有继承的关系是什么? [24.6] 私有继承和保护继承的访问规则是什么? 24.1 如何表示“私有继承”? 用 : priv

  • 问题内容: 为什么以下代码不起作用(Python 2.5.2)? 我想创建一个类似的类,但具有不同的功能。显然我的函数永远不会被调用。而是调用原始文件并失败,因为它需要3个参数,而我传入了一个。 这里发生了什么?这是一个线索吗? 谢谢! 问题答案: 关于其他几个答案,这与用C本身实现的日期无关。该方法不做任何事情,因为它们是 不可变的 对象,因此构造函数()应该完成所有工作。您会看到相同的行为将i

  • “为什么多重继承在java中是不可能的?”与“为什么java中不支持多重继承”这个问题有什么不同吗?或者两者是相互关联的。我知道这已经得到了回答,只是在寻找一个不同的地方,如果有的话,而不是为什么的答案。

  • 问题内容: 这是一个有趣的代码片段: 我知道子类不会继承其父级的私有成员,但是obj设法在其中调用它不应具有的访问权的方法。在编译时,obj是Superclass类型,在运行时是Subclass类型。 这可能与以下事实有关:对doSomething()的调用发生在驱动程序类内部,而该驱动程序类恰好是其自己的类(以及为什么可以首先调用doSomething()的原因)。 因此问题归结为,obj如何访

  • 问题内容: 因此,我有两个来自javascript.info的示例: 范例1: 范例2: 从示例2开始:当代码到达时,它在中找不到任何属性,因此它爬升到原型并在那里进行了更改。这就是为什么两只仓鼠都相等的原因,换句话说,它们的肚子也一样。 据此我了解,当编写并添加一个不存在的新属性时,解释器将沿着原型链向上移动,直到找到该属性,然后再进行更改。 但是在示例1中,发生了其他事情: 我们运行,它发生了

  • 本文向大家介绍再谈javascript原型继承,包括了再谈javascript原型继承的使用技巧和注意事项,需要的朋友参考一下 真正意义上来说Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承。 原型与原型链 说原型继承之前还是要先说说原型和原型链,毕竟这是实现原型继承的基础。 在Javascript中,每个函数都