是否有 Class 等同于函数上的原型变量?

Is there a Class equivalent to prototype variables on Functions?

如果我有以下代码:

function Thing() {}
Thing.prototype.cache = {};

var a = new Thing();
var b = new Thing();

a.cache === b.cache // true

我如何使用 proper Classes 重写此内容?

我知道 public class fields,但它们是在 实例 而不是 class 原型上定义的。

// For Example:
class Thing {
  cache = {}
}

var a = new Thing();
var b = new Thing();

a.cache === b.cache // false

您所实现的称为 class field,正如您在您的案例中注意到的那样,它等效于:

class Thing {
  constructor() {
    this.cache = {};
  }
}

你别无选择,只能像在 ES5 中那样将它附加到原型上,因为你在 class 中声明的所有内容都是:

  • 一个class字段(附加到实例)
  • 一个方法(附在原型上)
  • 一个静态字段(附加到class)

class Thing {
}

Thing.prototype.cache = {};

const obj1 = new Thing;
const obj2 = new Thing;

console.log(obj1.cache === obj2.cache);

我在这里发布了一个类似的问题:

附带说明一下,因为您没有使用 constructor,所以 class 是不必要的,因此您可以这样写:

const proto = { cache: {} };

const obj1 = Object.create(proto);
const obj2 = Object.create(proto);

console.log(obj1.cache === obj2.cache);

您想创建一个static class field

然后根据 class 名称定义 getter 和 setter。

Public static fields are useful when you want a field to exist only once per class, not on every class instance you create. This is useful for caches, fixed-configuration, or any other data you don't need to be replicated across instances.

Public static fields are declared using the static keyword. They are added to the class constructor at the time of class evaluation using Object.defineProperty(). They are accessed again from the class constructor.

  • Fields without initializers are initialized to undefined.
  • Public static fields are not reinitialized on subclasses, but can be accessed via the prototype chain.
  • When initializing fields, this refers to the class constructor. You can also reference it by name, and use super to get the superclass constructor (if one exists).

class Thing {
  static _cache = {};
  
  get cache() { return Thing._cache; }
  set cache(newValue) { Thing._cache = newValue; }
}

var a = new Thing();
var b = new Thing();

b.cache.key = "value";

console.log(a.cache === b.cache);
console.log(a.cache)

没有 class 语法可以将非方法放在原型上,你必须事后加上它们,像这样:

class Thing {}
Thing.prototype.cache = {}

// Example usage //

const thing1 = new Thing()
const thing2 = new Thing()
thing1.cache.x = 2
console.log(thing2.cache.x)

然而,将可变数据放在原型上被许多人视为神奇且难以遵循。这是实现非常相似效果的另一种方法。

// This can alternativly be a static, private variable on the class.
const thingCache = {}

class Thing {
  cache = thingCache
}

// Example usage //

const thing1 = new Thing()
const thing2 = new Thing()

thing1.cache.x = 2
console.log(thing2.cache.x)

但是,我真正建议的是将此 属性 设为 class 上的静态 属性 - 这就是静态属性的用途,共享单个数据在许多实例之间。

class Thing {
  static cache = {}
}

// Example usage //

Thing.cache.x = 2
console.log(Thing.cache.x)

// In some rare scenarios where you only have the instance,
// and not the original class, you can still retrieve the original class

const thing1 = new Thing()
const thing2 = new Thing()

thing1.constructor.cache.x = 2
console.log(thing2.constructor.cache.x)