本文共 8335 字,大约阅读时间需要 27 分钟。
typescript 静态
In Object-Oriented Programming, we write a lot of classes.
在面向对象编程中, 我们编写了许多类 。
Classes contain properties (methods and attributes) which hold variables and operations.
类包含保存变量和操作的属性 ( 方法和属性 )。
Every time we define the properties of a class, they are said to belong to either:
每当我们定义一个类的属性时,它们就被认为属于以下任何一个:
an instance of the class (an object created via constructor) OR
类的实例 (通过构造函数创建的对象)或
the class itself (we call this a class member)
班级本身 (我们称其为班级成员)
What do we mean by that?
那是什么意思?
How can properties belong to only the instance vs. only the class?
属性如何仅属于实例而不是类 ?
When we choose to use or omit the static
keyword, it changes who the properties belong to.
当我们选择使用或省略static
关键字时,它将更改属性所属的人。
Let's look at regular usage without the static
keyword.
让我们看看不带static
关键字的常规用法。
Normally, when we define properties on a class, the only time they can be accessed is after we've created an instance of that class or if we use this
to refer to the properties that will eventually reside on an instance of the object.
通常情况下,当我们在一个类中定义的属性,他们可以访问的唯一的一次是,我们已经创建了一个类的实例后,或者如果我们用this
来指代最终将驻留在对象的实例属性。
Take this early example from .
以为例。
type Genre = 'rock' | 'pop' | 'electronic' | 'rap'class Vinyl { public title: string; public artist: string; public genres: Genre[]; constructor (title: string, artist: string, genres: Genre[]) { this.title = title; this.artist = artist; this.genres = genres; } public printSummary (): void { console.log(`${this.title} is an album by ${this.artist}`); }}const vinyl = new Vinyl('Goo', 'Sonic Youth', ['rock']);console.log(vinyl.title) // 'Goo'console.log(vinyl.artist) // 'Sonic Youth'console.log(vinyl.genres) // ['rock']vinyl.printSummary(); // 'Goo is an album by Sonic Youth'
Each of the methods (printSummary(): void
) and attributes (title
, artist
, genres
) on the Vinyl
class are said to belong to an instance of the class.
Vinyl
类上的每个方法( printSummary(): void
)和属性( title
, artist
, genres
)都属于该类的实例 。
In the example, we were only able to access the properties title
, artist
and genres
directly from the object after it was created.
在示例中,创建对象后 ,我们只能直接从其访问title
, artist
和genres
属性。
console.log(vinyl.title) // This is valid!
Also note that when we use printSummary(): void
, we can access title
and artist
using the this
keyword:
还要注意,当我们使用printSummary(): void
,我们可以使用this
关键字访问title
和artist
:
class Vinyl { ... public printSummary (): void { console.log(`${this.title} is an album by ${this.artist}`); }}
That works because at this point, the resulting object / instance of Vinyl
owns those properties.
之所以可行,是因为此时, Vinyl
的最终对象/实例拥有这些属性。
If we check out , we can look at the compiled JavaScript for this code sample:
如果我们查看 ,我们可以查看此代码示例的已编译JavaScript:
"use strict";class Vinyl { constructor(title, artist, genres) { this.title = title; this.artist = artist; this.genres = genres; } printSummary() { console.log(`${this.title} is an album by ${this.artist}`); }}const vinyl = new Vinyl('Goo', 'Sonic Youth', ['rock']);console.log(vinyl.title); // 'Goo'console.log(vinyl.artist); // 'Sonic Youth'console.log(vinyl.genres); // ['rock']vinyl.printSummary(); // 'Goo is an album by Sonic Youth'
The resulting JavaScript looks nearly identical.
产生JavaScript看起来几乎相同 。
Let's talk a bit about what happens when the properties are owned by the class.
让我们来谈一谈当属性归类所有时会发生什么。
When we use the static
keyword on properties we define on a class, they belong to the class itself.
当在类上定义的属性上使用static
关键字时,它们属于类本身 。
That means that we cannot access those properties from an instance of the class.
这意味着我们无法从类的实例访问那些属性。
We can only access the properties directly by referencing the class itself.
我们只能通过引用类本身直接访问属性。
To demonstrate, let's add a counter NUM_VINYL_CREATED
that increments the number of times that a Vinyl
was created.
为了演示,让我们添加一个计数器NUM_VINYL_CREATED
,该计数器增加创建Vinyl
的次数。
type Genre = 'rock' | 'pop' | 'electronic' | 'rap'class Vinyl { public title: string; public artist: string; public genres: Genre[]; public static NUM_VINYL_CREATED: number = 0; constructor (title: string, artist: string, genres: Genre[]) { this.title = title; this.artist = artist; this.genres = genres; Vinyl.NUM_VINYL_CREATED++; // increment number of vinyl created console.log(Vinyl.NUM_VINYL_CREATED) } public printSummary (): void { console.log(`${this.title} is an album by ${this.artist}`); }}let goo = new Vinyl ('Goo', 'Sonic Youth', ['rock']);// prints out 0let daydream = new Vinyl ('Daydream Nation', 'Sonic Youth', ['rock']);// prints out 1
Because the properties can only be accessed through the class itself, we can't do:
因为只能通过类本身访问属性,所以我们不能这样做:
let goo = new Vinyl ('Goo', 'Sonic Youth', ['rock']);goo.MAX_GENRES_PER_VINYL // Errorgoo.NUM_VINYL_CREATED // Error
You might have heard of a term called Class Members. An attribute or a method is a class member because they can ONLY be accessed through the class itself; therefore, they're members of the class.
您可能听说过一个称为“ 班级成员 ”的术语。 属性或方法是类成员,因为只能通过类本身来访问它们。 因此,他们是班上的成员。
That's great and all, but when would you want to use static properties?
太好了,但是什么时候您想使用静态属性?
Before you add that attribute or method, as yourself:
在自己添加该属性或方法之前,请先:
Will this property ever need to be used by another class, without having an instance of this class?
将这个属性在任何时候需要由其他类使用,而不必这个类的一个实例?
In other words, should I need to call it on an object created by this class? If yes, then continue normally.
换句话说,是否需要在此类创建的对象上调用它? 如果是,则正常继续。
If no, then you might want to make a static
member.
如果否,那么您可能想成为static
成员。
to implement a factory method
to required in order to create an instance of the class
实现factory method
以创建类实例所需
to use an abstract factory
in order
使用abstract factory
to perform validation logic on atttributes for that class (use instead)
对该类的属性执行验证逻辑(改为使用 )
To demonstrate a worthwhile scenario, let's add a static
MAX_GENRES_PER_VINYL
attribute to "document a constraint" that a Vinyl
may only have at max 2 different types of Genres
.
为了演示一个有价值的场景,让我们添加一个static
MAX_GENRES_PER_VINYL
属性来“记录约束”,一个Vinyl
最多只能具有2种不同类型的Genres
。
type Genre = 'rock' | 'pop' | 'electronic' | 'rap'class Vinyl { public title: string; public artist: string; public genres: Genre[]; public static MAX_GENRES_PER_VINYL: number = 2; constructor (title: string, artist: string, genres: Genre[]) { this.title = title; this.artist = artist; this.genres = genres; } public printSummary (): void { console.log(`${this.title} is an album by ${this.artist}`); }}
And then let's add an addGenre(genre: Genre): void
method to enforce this business rule.
然后,我们添加一个addGenre(genre: Genre): void
方法来实施此业务规则。
type Genre = 'rock' | 'pop' | 'electronic' | 'rap'class Vinyl { public title: string; public artist: string; public genres: Genre[]; public static MAX_GENRES_PER_VINYL: number = 2; constructor (title: string, artist: string, genres: Genre[]) { this.title = title; this.artist = artist; this.genres = genres; } public addGenre (genre: Genre): void { // Notice that in order to reference the value, we have go through the class // itself (Vinyl), not through an instance of the class (this). const maxLengthExceeded = this.genres.length < Vinyl.MAX_GENRES_PER_VINYL; const alreadyAdded = this.genres.filter((g) => g === genre).length !== 0; if (!maxLengthExceeded && !alreadyAdded) { this.genres.push(genre); } } public printSummary (): void { console.log(`${this.title} is an album by ${this.artist}`); }}
If you enjoyed this article, you should . I write about Advanced TypeScript & Node.js best practices for large-scale applications and teach developers how to write flexible, maintainable software.
如果您喜欢这篇文章,则应该 。 我写了针对大型应用程序的Advanced TypeScript和Node.js最佳实践,并教开发人员如何编写灵活,可维护的软件。
翻译自:
typescript 静态
转载地址:http://hphwd.baihongyu.com/