22# Class 基本语法
33
44``` quote author="Wikipedia"
5- 在面向对象的编程中,class 是用于创建对象的可扩展的程序代码模版,它为对象提供了状态(成员变量)的初始值和行为(成员函数和方法 )的实现。
5+ 在面向对象的编程中,* class* 是用于创建对象的可扩展的程序代码模版,它为对象提供了状态(成员变量)的初始值和行为(成员函数或方法 )的实现。
66```
77
8- 在日常开发中,我们经常要创建许多相同类型的对象,比如用户 (users)、商品(goods)或者其他任何东西 。
8+ 在日常开发中,我们经常需要创建许多相同类型的对象,例如用户 (users)、商品(goods)或者任何其他东西 。
99
10- 在 < info:constructor-new > 章节中我们已经知道 ,` new function ` 可以做到这样 。
10+ 正如我们在 < info:constructor-new > 一章中已经学到的 ,` new function ` 可以帮助我们实现这种需求 。
1111
12- 但是在现代 JavaScript 中,有一个更为高级的类 (class)构造方式,它引入了对于面向对象编程很有用的功能 。
12+ 但在现代 JavaScript 中,还有一个更高级的“类 (class)” 构造方式,它引入许多非常棒的新功能,这些功能对于面向对象编程很有用 。
1313
14- ## “ class” 语法
14+ ## " class" 语法
1515
1616基本语法是:
1717``` js
@@ -25,9 +25,9 @@ class MyClass {
2525}
2626```
2727
28- 然后通过 ` new MyClass() ` 来创建具有上述列出的所有方法的新对象。
28+ 然后使用 ` new MyClass() ` 来创建具有上述列出的所有方法的新对象。
2929
30- 通过 ` new ` 关键词创建的对象会自动调用 ` constructor() ` 方法,因此我们可以在 ` constructor() ` 里初始化对象 。
30+ ` new ` 会自动调用 ` constructor() ` 方法,因此我们可以在 ` constructor() ` 中初始化对象 。
3131
3232例如:
3333
@@ -44,29 +44,29 @@ class User {
4444
4545}
4646
47- // 使用方法 :
47+ // 用法 :
4848let user = new User (" John" );
4949user .sayHi ();
5050```
5151
5252当 ` new User("John") ` 被调用:
53531 . 一个新对象被创建。
54- 2 . ` constructor ` 构造器使用给定的参数运行 ,并为其分配 ` this.name ` 。
54+ 2 . ` constructor ` 使用给定的参数运行 ,并为其分配 ` this.name ` 。
5555
56- ...然后我们就可以调用诸如 ` user.sayHi ` 这样的方法了 。
56+ ……然后我们就可以调用对象方法了,例如 ` user.sayHi ` 。
5757
5858
59- ``` warn header="类方法之间没有逗号 "
60- 经验不足的开发者常犯的语法错误是在类方法之间加一个逗号 。
59+ ``` warn header="类的方法之间没有逗号 "
60+ 对于新手开发人员来说,常见的陷阱是在类的方法之间放置逗号,这会导致语法错误 。
6161
62- 这里的符号不要与对象字面量相混淆, 在类中,不需要逗号。
62+ 不要把这里的符号与对象字面量相混淆。 在类中,不需要逗号。
6363```
6464
6565## 什么是 class?
6666
6767所以,` class ` 到底是什么?正如人们可能认为的那样,这不是一个全新的语言级实体。
6868
69- 让我们揭开其神秘面纱,看看类究竟是什么。这将会有助于你理解许多复杂的方面 。
69+ 让我们揭开其神秘面纱,看看类究竟是什么。这将有助于我们理解许多复杂的方面 。
7070
7171在 JavaScript 中,类是一种函数。
7272
@@ -84,68 +84,67 @@ alert(typeof User); // function
8484*/ ! *
8585```
8686
87- ` class User {...} ` 构造器内部为我们做了什么:
88- 1 . 创建一个以 ` User ` 为名称的函数,这是类声明的结果。
89- - 函数代码来自于 ` constructor ` 中的方法(如果我们不写这样的方法,那么就假设它为空的)。
90- 2 . 储存所有方法,例如 ` User.prototype ` 中的 ` sayHi ` 。
87+ ` class User {...} ` 构造实际上做了如下的事儿:
9188
92- 然后,对于新的对象,当我们调用方法时,它取自原型,就像我们在 < info:function-prototype > 章节中描述的那样。所以 ` new User ` 对象可以访问类中的方法。
89+ 1 . 创建一个名为 ` User ` 的函数,该函数成为类声明的结果。该函数的代码来自于 ` constructor ` 方法(如果我们不编写这种方法,那么它就被假定为空)。
90+ 2 . 存储类中的方法,例如 ` User.prototype ` 中的 ` sayHi ` 。
9391
94- 我们可以将 ` class User` 声明结果解释为:
92+ 当 ` new User` 对象被创建后,当我们调用其方法时,它会从原型中获取对应的方法,正如我们在 < info:function-prototype > 一章中所讲的那样。因此,对象 ` new User ` 可以访问类中的方法。
9593
96- ![ ] ( class-user.svg )
94+ 我们可以将 ` class User ` 声明的结果解释为:
9795
98- 下面这些代码很好的解释了它们:
96+ ![ ] ( class-user.svg )
9997
98+ 下面这些代码很好地解释了它们:
10099
101100``` js run
102101class User {
103102 constructor (name ) { this .name = name; }
104103 sayHi () { alert (this .name ); }
105104}
106105
107- // 类是函数
106+ // class 是函数 function
108107alert (typeof User); // function
109108
110- // ...或者,更确切地说是构造方法
109+ // ...或者,更确切地说,是构造器方法
111110alert (User === User .prototype .constructor ); // true
112111
113- // User.prototype 中的方法,比如 :
112+ // 方法在 User.prototype 中,例如 :
114113alert (User .prototype .sayHi ); // alert(this.name);
115114
116- // 实际上在原型中有两个方法
115+ // 在原型中实际上有两个方法
117116alert (Object .getOwnPropertyNames (User .prototype )); // constructor, sayHi
118117```
119118
120119## 不仅仅是语法糖
121120
122- 人们常说 ` class ` 是 JavaScript 中的语法糖,主要是因为我们可以在没有 ` class ` 的情况下声明同样的内容 :
121+ 人们常说 ` class ` 是一个语法糖(旨在使内容更易阅读,但不引入任何新内容的语法),因为我们实际上可以在没有 ` class ` 的情况下声明相同的内容 :
123122
124123``` js run
125- // 以纯函数的重写 User 类
124+ // 用纯函数重写 class User
126125
127126// 1. 创建构造器函数
128127function User (name ) {
129128 this .name = name;
130129}
131- // 任何函数原型默认具有构造器属性 ,
130+ // 任何函数原型默认都具有构造器属性 ,
132131// 所以,我们不需要创建它
133132
134- // 2. 向原型中添加方法
133+ // 2. 将方法添加到原型
135134User .prototype .sayHi = function () {
136135 alert (this .name );
137136};
138137
139- // 使用方法 :
138+ // 用法 :
140139let user = new User (" John" );
141140user .sayHi ();
142141```
143142
144- 这和定义的结果大致相同 。因此,这确实是 ` class ` 被视为一种定义构造函数及其原型方法的语法糖的理由 。
143+ 这个定义的结果与使用类得到的结果基本相同 。因此,这确实是将 ` class ` 视为一种定义构造函数及其原型方法的语法糖的理由 。
145144
146- 尽管它们存在重大差异 :
145+ 尽管,它们之间存在着重大差异 :
147146
148- 1 . 首先,通过 ` class ` 创建的函数是由特殊内部属性标记的 ` [[FunctionKind]]:"classConstructor" ` 。所以,相较于手动创建它还是有点不同的 。
147+ 1 . 首先,通过 ` class ` 创建的函数具有特殊的内部属性标记 ` [[FunctionKind]]:"classConstructor" ` 。因此,它与手动创建并不完全相同 。
149148
150149 不像普通函数,调用类构造器时必须要用 ` new ` 关键词:
151150
@@ -155,10 +154,10 @@ user.sayHi();
155154 }
156155
157156 alert (typeof User); // function
158- User (); // Error: 没有 ‘new’ 关键词,类构造器 User 无法调用
157+ User (); // Error: Class constructor User cannot be invoked without 'new'
159158 ```
160159
161- 此外,大多数 JavaScript 引擎中的类构造函数的字符串表示形式都以 “ class ” 开头
160+ 此外,大多数 JavaScript 引擎中的类构造器的字符串表示形式都以 " class... " 开头
162161
163162 ` ` ` js run
164163 class User {
@@ -169,21 +168,20 @@ user.sayHi();
169168 ` ` `
170169
1711702. 类方法不可枚举。
172- 对于 ` "prototype"` 中的所有方法,类定义将 ` enumerable` 标记设为 ` false。
171+ 类定义将 ` "prototype"` 中的所有方法的 ` enumerable` 标志设置为 ` false` 。
173172
174173 这很好,因为如果我们对一个对象调用 ` for..in` 方法,我们通常不希望 class 方法出现。
175174
176- 3. 类默认使用 ` use strict` 。
177- 在类构造函数中的所有方法自动使用严格模式。
178-
175+ 3. 类总是使用 ` use strict` 。
176+ 在类构造中的所有代码都将自动进入严格模式。
179177
180- 此外,除了它的基础操作外, ` class ` 语法也带来许多其他功能 ,我们稍后将会探索它们。
178+ 此外,` class` 语法还带来了许多其他功能 ,我们稍后将会探索它们。
181179
182- ## 类表达式(Class Expression)
180+ ## 类表达式
183181
184- 正如函数一样,类可以在另外一个表达式中定义,传递(passed around),返回(returned),调用(assigned)等
182+ 就像函数一样,类可以在另外一个表达式中被定义,被传递,被返回,被赋值等。
185183
186- 这里是类表达式的例子 :
184+ 这是一个类表达式的例子 :
187185
188186` ` ` js
189187let User = class {
@@ -193,49 +191,49 @@ let User = class {
193191};
194192` ` `
195193
196- 类似于命名函数表达式(Named Function Expressions),类表达式可能也可能没有名称 。
194+ 类似于命名函数表达式(Named Function Expressions),类表达式可能也应该有一个名字 。
197195
198- 如果类表达式有名称,它仅在类内部可见 :
196+ 如果类表达式有名字,那么该名字仅在类内部可见 :
199197
200198` ` ` js run
201- // “命名类表达式”
202- // ( 规范中没有这样的术语,但是它和命名函数表达式类似)
199+ // “命名类表达式(Named Class Expression) ”
200+ // ( 规范中没有这样的术语,但是它和命名函数表达式类似)
203201let User = class *!*MyClass*/!* {
204202 sayHi() {
205- alert (MyClass); // MyClass 仅在其内部可见
203+ alert(MyClass); // MyClass 这个名字仅在类内部可见
206204 }
207205};
208206
209207new User().sayHi(); // 正常运行,显示 MyClass 中定义的内容
210208
211- alert (MyClass); // 错误 ,MyClass 在外部不可见
209+ alert(MyClass); // error ,MyClass 在外部不可见
212210` ` `
213211
214212
215- 我们甚至可以 “按需”动态创建类 ,就像这样:
213+ 我们甚至可以动态地 “按需”创建类 ,就像这样:
216214
217215` ` ` js run
218216function makeClass(phrase) {
219- // 声明并返回类
217+ // 声明一个类并返回它
220218 return class {
221219 sayHi() {
222220 alert(phrase);
223221 };
224222 };
225223}
226224
227- // 创建新类
225+ // 创建一个新的类
228226let User = makeClass("Hello");
229227
230228new User().sayHi(); // Hello
231229` ` `
232230
233231
234- ## Getters/setters 及其他 shorthands
232+ ## Getters/ setters 及其他速记
235233
236- 就像对象字面量,类可能包括 getters/setters,generators, 计算属性(computed properties)等。
234+ 就像对象字面量,类可能包括 getters/ setters,计算属性(computed properties)等。
237235
238- 这是使用 ` get/set ` 实现 ` user.name ` 的示例:
236+ 这是一个使用 ` get/set` 实现 ` user.name` 的示例:
239237
240238` ` ` js run
241239class User {
@@ -266,7 +264,7 @@ class User {
266264let user = new User("John");
267265alert(user.name); // John
268266
269- user = new User (" " ); // Name too short.
267+ user = new User(""); // Name is too short.
270268` ` `
271269
272270类声明在 ` User.prototype` 中创建 getters 和 setters,就像这样:
@@ -284,13 +282,14 @@ Object.defineProperties(User.prototype, {
284282});
285283` ` `
286284
287- 这是计算属性的例子 :
285+ 这是一个 ` [...] ` 中有计算属性名称(computed property name)的例子 :
288286
289287` ` ` js run
290- function f () { return " sayHi" ; }
291-
292288class User {
293- [f ()]() {
289+
290+ *!*
291+ ['say' + 'Hi']() {
292+ */!*
294293 alert("Hello");
295294 }
296295
@@ -299,53 +298,55 @@ class User {
299298new User().sayHi();
300299` ` `
301300
302- 对于 generator 方法,类似的,在它前面添加 ` * ` 。
303-
304301## Class 属性
305302
306303` ` ` warn header="旧的浏览器可能需要 polyfill"
307304类级别的属性是最近才添加到语言中的。
308305` ` `
309306
310- 上面的例子中 ,` User ` 只有方法。现在我们为其添加属性 :
307+ 在上面的例子中 ,` User` 只有方法。现在我们为其添加一个属性 :
311308
312309` ` ` js run
313310class User {
311+ *!*
314312 name = "Anonymous";
313+ */!*
315314
316315 sayHi() {
317316 alert(` Hello, ${this .name }! ` );
318317 }
319318}
320319
321320new User().sayHi();
322- ```
323321
324- 属性不在 ` User.prototype ` 内。相反它是通过 ` new ` 分别为每个对象创建的。所以,该属性永远不会在同一个类的不同对象之间共享。
322+ alert(User.prototype.sayHi); // 被放在 User.prototype 中
323+ alert(User.prototype.name); // undefined,没有被放在 User.prototype 中
324+ ` ` `
325325
326+ ` name` 属性没有被放在 ` User.prototype` 中。相反,它是在调用构造器之前通过 ` new` 分创建的,它是对象自身的属性。
326327
327328## 总结
328329
329- 基本的类语法看起来是这样的 :
330+ 基本的类语法看起来像这样 :
330331
331332` ` ` js
332333class MyClass {
333- prop = value; // field
334+ prop = value; // 属性
334335
335336 constructor(...) { // 构造器
336337 // ...
337338 }
338339
339- method (... ) {} // 方法
340+ method(...) {} // method
340341
341342 get something(...) {} // getter 方法
342- set something (... ) {} // setter 方法
343+ set something(...) {} // setter 方法
343344
344- [Symbol .iterator ]() {} // 计算 name/symbol 名方法
345+ [Symbol.iterator]() {} // 有计算名称(computed name)的方法(此处为 symbol)
345346 // ...
346347}
347348` ` `
348349
349- 技术上来说,` MyClass ` 是一个函数(我们提供作为 ` constructor ` 的那个),而 methods, getters 和 settors 都被写入 ` MyClass.prototype ` 。
350+ 技术上来说,` MyClass` 是一个函数(我们提供作为 ` constructor` 的那个),而 methods、 getters 和 settors 都被写入了 ` MyClass.prototype` 。
350351
351- 在下一章,我们将会进一步研究类,包括继承在内的其他功能 。
352+ 在下一章,我们将会进一步学习类的相关知识,包括继承和其他功能 。
0 commit comments