简体   繁体   English

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

[英]Is there a Class equivalent to prototype variables on Functions?

If I have the following code:如果我有以下代码:

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

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

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

How might I re-write this using proper Classes ?我如何使用适当的 Classes重写它?

I know about public class fields , but those are defined on the instance rather than on the class prototype.我知道公共 class 字段,但这些字段是在实例上定义的,而不是在 class 原型上定义的。

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

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

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

There's no class syntax to put non-methods on the prototype, you'll have to slap them on afterwards, like this:没有 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)

However, putting mutable data on the prototype is seen by many as magical and difficult to follow.然而,将可变数据放在原型上被许多人视为神奇且难以遵循。 Here's another way to achieve a very similar effect.这是实现非常相似效果的另一种方法。

 // 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)

But, what I would really recommend is to just make this property a static property on the class - that's what static properties are for, sharing a single piece of data between many instances.但是,我真正建议的是在 class 上将此属性设为 static 属性 - 这就是 static 属性的用途,在许多实例之间共享单个数据。

 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)

What you have implemented is called class field , as you noticed in your case it's an equivalent of:您实施的称为class field ,正如您在您的案例中注意到的那样,它相当于:

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

You have no other choice than attaching it to the prototype just like you'd do in ES5, because everything you declare inside a class is either:除了像在 ES5 中那样将它附加到原型之外,您别无选择,因为您在 class 中声明的所有内容都是:

  • A class field (attached to the instance)一个 class 字段(附加到实例)
  • A method (attached to the prototype)一个方法(附在原型上)
  • A static field (attached to the class)一个 static 字段(附加到类)

 class Thing { } Thing.prototype.cache = {}; const obj1 = new Thing; const obj2 = new Thing; console.log(obj1.cache === obj2.cache);

I have posted a similar question here: Not able to update a class property in ES6我在这里发布了一个类似的问题: Not able to update a class property in ES6

As a side note, as you're not using a constructor , the class is needless so you could write this:附带说明一下,由于您没有使用constructor ,因此class是不必要的,因此您可以这样写:

 const proto = { cache: {} }; const obj1 = Object.create(proto); const obj2 = Object.create(proto); console.log(obj1.cache === obj2.cache);

You want to create a static class field您想创建一个static class 字段

Then define getters and setters based off the class name.然后根据 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.当您希望一个字段在每个 class 中仅存在一次时,公共 static 字段非常有用,而不是在您创建的每个 class 实例上。 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.公共 static 字段使用 static 关键字声明。 They are added to the class constructor at the time of class evaluation using Object.defineProperty() .在使用Object.defineProperty()评估 class 时,它们被添加到 class 构造函数中。 They are accessed again from the class constructor.从 class 构造函数再次访问它们。

  • Fields without initializers are initialized to undefined.没有初始化器的字段被初始化为未定义。
  • Public static fields are not reinitialized on subclasses, but can be accessed via the prototype chain.公共 static 字段不会在子类上重新初始化,但可以通过原型链访问。
  • When initializing fields, this refers to the class constructor.初始化字段时, this指的是 class 构造函数。 You can also reference it by name, and use super to get the superclass constructor (if one exists).您也可以通过名称引用它,并使用super获取超类构造函数(如果存在)。

 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)

As Scotty Jamison said, the class syntax still does not provide a way to create fields on the prototype itself, so you'll have to do it with [class].prototype.field .正如 Scotty Jamison 所说,class 语法仍然没有提供在原型本身上创建字段的方法,因此您必须使用[class].prototype.field来完成。 However, if you wish to do so within the class declaration itself, you can use static blocks:但是,如果您希望在 class 声明本身中这样做,您可以使用 static 块:

class Thing {
    static {
        this.prototype.boofar = {};
    }
}

Code inside a static block will run when the class is initialized, with this bound to the class itself. static 块中的代码将在 class 初始化时运行, this与 class 本身绑定。 This is arguably more confusing than just assigning the value after the class declaration, as using static might suggest a static property, not an inherited one.可以说,这比仅在 class 声明之后分配值更令人困惑,因为使用static可能建议使用 static 属性,而不是继承的属性。 Still, it's nice for the class to not depend on external code.尽管如此,class 不依赖外部代码还是不错的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM