11# Class和Module
22
3- ## Class
4-
5- ### 基本语法
3+ ## Class基本语法
64
75** (1)概述**
86
@@ -11,12 +9,12 @@ ES5通过构造函数,定义并生成新对象。下面是一个例子。
119``` javascript
1210
1311function Point (x ,y ){
14- this .x = x;
15- this .y = y;
12+ this .x = x;
13+ this .y = y;
1614}
1715
1816Point .prototype .toString = function () {
19- return ' (' + this .x + ' , ' + this .y + ' )' ;
17+ return ' (' + this .x + ' , ' + this .y + ' )' ;
2018}
2119
2220```
@@ -109,7 +107,7 @@ point.toString() // (2, 3)
109107point .hasOwnProperty (' x' ) // true
110108point .hasOwnProperty (' y' ) // true
111109point .hasOwnProperty (' toString' ) // false
112- point .__proto__ .hasOwnProperty (' toString' ) // false
110+ point .__proto__ .hasOwnProperty (' toString' ) // true
113111
114112```
115113
@@ -125,9 +123,9 @@ p1.__proto__ === p2.__proto__
125123
126124```
127125
128- 上面代码中,p1和p2都是Point的实例,它们的原型都是Point,所以\_ _ proto __ 属性是相等的 。
126+ 上面代码中,p1和p2都是Point的实例,它们的原型都是Point,所以\_\_ proto \_\_ 属性是相等的 。
129127
130- 这也意味着,可以通过\_ _ proto __ 属性为Class添加方法 。
128+ 这也意味着,可以通过\_\_ proto \_\_ 属性为Class添加方法 。
131129
132130``` javascript
133131
@@ -139,7 +137,7 @@ p1.__proto__.printName = function () { return 'Oops' };
139137p1 .printName () // "Oops"
140138p2 .printName () // "Oops"
141139
142- var p3 = new Point (4 ,2 );
140+ var p3 = new Point (4 ,2 );
143141p3 .printName () // "Oops"
144142
145143```
@@ -210,8 +208,8 @@ class Foo {}
210208
211209``` javascript
212210
213- {
214- let Foo = class {};
211+ {
212+ let Foo = class {};
215213 class Bar extends Foo {
216214 }
217215}
@@ -224,9 +222,9 @@ class Foo {}
224222
225223类和模块的内部,默认就是严格模式,所以不需要使用` use strict ` 指定运行模式。考虑到未来所有的代码,其实都是运行在模块之中,所以ES6实际上把整个语言升级到了严格模式。
226224
227- ### Class的继承
225+ ## Class的继承
228226
229- ** (1) 基本用法**
227+ ### 基本用法
230228
231229Class之间可以通过extends关键字,实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。
232230
@@ -248,14 +246,14 @@ class ColorPoint extends Point {
248246 }
249247
250248 toString () {
251- return this .color + ' ' + super (); // 等同于parent.toString()
249+ return this .color + ' ' + super . toString (); // 等同于parent.toString()
252250 }
253251
254252}
255253
256254```
257255
258- 上面代码中,constructor方法和toString方法之中,都出现了super关键字,它指代父类的同名方法。在constructor方法内,super指代父类的constructor方法;在toString方法内,super指代父类的toString方法 。
256+ 上面代码中,constructor方法和toString方法之中,都出现了super关键字,它指代父类的实例(即父类的this对象) 。
259257
260258子类必须在constructor方法中调用super方法,否则新建实例时会报错。
261259
@@ -267,7 +265,7 @@ class ColorPoint extends Foo {
267265 constructor () {
268266 }
269267}
270-
268+
271269let cp = new ColorPoint (); // ReferenceError
272270
273271```
@@ -282,7 +280,7 @@ constructor(...args) {
282280
283281```
284282
285- 另一个需要注意的地方是,只有调用super方法之后, 才可以使用this关键字,否则会报错。
283+ 另一个需要注意的地方是,在子类的构造函数中,只有调用super之后, 才可以使用this关键字,否则会报错。这是因为没有调用父类的构造函数,就无法子类实例的构建 。
286284
287285``` javascript
288286
@@ -292,7 +290,7 @@ class Point {
292290 this .y = y;
293291 }
294292}
295-
293+
296294class ColorPoint extends Point {
297295 constructor (x , y , color ) {
298296 this .color = color; // ReferenceError
@@ -303,7 +301,7 @@ class ColorPoint extends Point {
303301
304302```
305303
306- 上面代码中,子类的constructor方法没有调用super方法之前 ,就使用this关键字,结果报错,而放在super方法之后就是正确的。
304+ 上面代码中,子类的constructor方法没有调用super之前 ,就使用this关键字,结果报错,而放在super方法之后就是正确的。
307305
308306下面是生成子类实例的代码。
309307
@@ -318,7 +316,7 @@ cp instanceof Point // true
318316
319317上面代码中,实例对象cp同时是ColorPoint和Point两个类的实例,这与ES5的行为完全一致。
320318
321- ** (2) prototype属性**
319+ ### prototype属性
322320
323321Class作为构造函数的升级,也有自己的prototype属性,其规则与ES5构造函数的prototype属性一致。
324322
@@ -346,7 +344,7 @@ C.prototype === Object
346344
347345上面代码中,子类的prototype属性都指向父类。如果一个类是基类(即不存在任何继承),那么它的原型指向` Function.prototype ` 。
348346
349- ** (3) Object.getPrototypeOf方法 **
347+ ### Object.getPrototypeOf()
350348
351349Object.getPrototypeOf方法可以用来从子类上获取父类。
352350
@@ -357,9 +355,9 @@ Object.getPrototypeOf(ColorPoint) === Point
357355
358356```
359357
360- ** (4) \_ _ proto \_ _ 属性 **
358+ ### \_\_ proto \_\_ 属性
361359
362- 父类和子类的\_ _ proto \_ _ 属性 ,指向是不一样的。
360+ 父类和子类的\_\_ proto \_\_ 属性 ,指向是不一样的。
363361
364362``` javascript
365363
@@ -371,12 +369,12 @@ p2.__proto__.__proto__ === p1.__proto__ // true
371369
372370```
373371
374- 通过子类的\_ _ proto \_ _ 属性 ,可以修改父类。
372+ 通过子类的\_\_ proto \_\_ 属性 ,可以修改父类。
375373
376374``` javascript
377375
378- p2 .__proto__ .__proto__ .printName = function () {
379- console .log (' Ha' );
376+ p2 .__proto__ .__proto__ .printName = function () {
377+ console .log (' Ha' );
380378};
381379
382380p1 .printName () // "Ha"
@@ -385,15 +383,15 @@ p1.printName() // "Ha"
385383
386384上面代码在ColorPoint的实例p2上向Point类添加方法,结果影响到了Point的实例p1。
387385
388- ** (5) 构造函数的继承**
386+ ### 构造函数的继承
389387
390388下面是一个继承原生的Array构造函数的例子。
391389
392390``` javascript
393391
394392class MyArray extends Array {
395- constructor (... args ) {
396- super (... args);
393+ constructor (... args ) {
394+ super (... args);
397395 }
398396}
399397
@@ -408,14 +406,14 @@ arr[1] = 12;
408406
409407``` javascript
410408
411- class MyError extends Error {
409+ class MyError extends Error {
412410}
413411
414412throw new MyError (' Something happened!' );
415413
416414```
417415
418- ### 取值函数getter和存值函数setter
416+ ## class的取值函数(getter)和存值函数(setter)
419417
420418与ES5一样,在Class内部可以使用get和set关键字,对某个属性设置存值函数和取值函数。
421419
@@ -442,7 +440,7 @@ inst.prop
442440
443441上面代码中,prop属性有对应的存值函数和取值函数,因此赋值和读取行为都被自定义了。
444442
445- ### Generator方法
443+ ## Class的Generator方法
446444
447445如果某个方法之前加上星号(* ),就表示该方法是一个Generator函数。
448446
@@ -458,7 +456,7 @@ class Foo {
458456 }
459457 }
460458}
461-
459+
462460for (let x of new Foo (' hello' , ' world' )) {
463461 console .log (x);
464462}
@@ -469,7 +467,7 @@ for (let x of new Foo('hello', 'world')) {
469467
470468上面代码中,Foo类的Symbol.iterator方法前有一个星号,表示该方法是一个Generator函数。Symbol.iterator方法返回一个Foo类的默认遍历器,for...of循环会自动调用这个遍历器。
471469
472- ### 静态方法
470+ ## Class的静态方法
473471
474472类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
475473
@@ -500,7 +498,7 @@ class Foo {
500498 return ' hello' ;
501499 }
502500}
503-
501+
504502class Bar extends Foo {
505503}
506504
0 commit comments