1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-28 21:32:20 +00:00

edit class

This commit is contained in:
Ruan Yifeng 2015-04-08 13:52:58 +08:00
parent 6129931efc
commit eb5b1f07a9

View File

@ -1,8 +1,6 @@
# Class和Module # Class和Module
## Class ## Class基本语法
### 基本语法
**1概述** **1概述**
@ -11,12 +9,12 @@ ES5通过构造函数定义并生成新对象。下面是一个例子。
```javascript ```javascript
function Point(x,y){ function Point(x,y){
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
Point.prototype.toString = function () { Point.prototype.toString = function () {
return '('+this.x+', '+this.y+')'; return '('+this.x+', '+this.y+')';
} }
``` ```
@ -109,7 +107,7 @@ point.toString() // (2, 3)
point.hasOwnProperty('x') // true point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // false point.__proto__.hasOwnProperty('toString') // true
``` ```
@ -125,9 +123,9 @@ p1.__proto__ === p2.__proto__
``` ```
上面代码中p1和p2都是Point的实例它们的原型都是Point所以\__proto__属性是相等的。 上面代码中p1和p2都是Point的实例它们的原型都是Point所以\_\_proto\_\_属性是相等的。
这也意味着,可以通过\__proto__属性为Class添加方法。 这也意味着,可以通过\_\_proto\_\_属性为Class添加方法。
```javascript ```javascript
@ -139,7 +137,7 @@ p1.__proto__.printName = function () { return 'Oops' };
p1.printName() // "Oops" p1.printName() // "Oops"
p2.printName() // "Oops" p2.printName() // "Oops"
var p3 = new Point(4,2); var p3 = new Point(4,2);
p3.printName() // "Oops" p3.printName() // "Oops"
``` ```
@ -210,8 +208,8 @@ class Foo {}
```javascript ```javascript
{ {
let Foo = class {}; let Foo = class {};
class Bar extends Foo { class Bar extends Foo {
} }
} }
@ -224,9 +222,9 @@ class Foo {}
类和模块的内部,默认就是严格模式,所以不需要使用`use strict`指定运行模式。考虑到未来所有的代码其实都是运行在模块之中所以ES6实际上把整个语言升级到了严格模式。 类和模块的内部,默认就是严格模式,所以不需要使用`use strict`指定运行模式。考虑到未来所有的代码其实都是运行在模块之中所以ES6实际上把整个语言升级到了严格模式。
### Class的继承 ## Class的继承
**1基本用法** ### 基本用法
Class之间可以通过extends关键字实现继承这比ES5的通过修改原型链实现继承要清晰和方便很多。 Class之间可以通过extends关键字实现继承这比ES5的通过修改原型链实现继承要清晰和方便很多。
@ -248,14 +246,14 @@ class ColorPoint extends Point {
} }
toString() { toString() {
return this.color+' '+super(); // 等同于parent.toString() return this.color + ' ' + super.toString(); // 等同于parent.toString()
} }
} }
``` ```
上面代码中constructor方法和toString方法之中都出现了super关键字它指代父类的同名方法。在constructor方法内super指代父类的constructor方法在toString方法内super指代父类的toString方法 上面代码中constructor方法和toString方法之中都出现了super关键字它指代父类的实例即父类的this对象
子类必须在constructor方法中调用super方法否则新建实例时会报错。 子类必须在constructor方法中调用super方法否则新建实例时会报错。
@ -267,7 +265,7 @@ class ColorPoint extends Foo {
constructor() { constructor() {
} }
} }
let cp = new ColorPoint(); // ReferenceError let cp = new ColorPoint(); // ReferenceError
``` ```
@ -282,7 +280,7 @@ constructor(...args) {
``` ```
另一个需要注意的地方是只有调用super方法之后才可以使用this关键字否则会报错。 另一个需要注意的地方是,在子类的构造函数中,只有调用super之后才可以使用this关键字否则会报错。这是因为没有调用父类的构造函数,就无法子类实例的构建。
```javascript ```javascript
@ -292,7 +290,7 @@ class Point {
this.y = y; this.y = y;
} }
} }
class ColorPoint extends Point { class ColorPoint extends Point {
constructor(x, y, color) { constructor(x, y, color) {
this.color = color; // ReferenceError this.color = color; // ReferenceError
@ -303,7 +301,7 @@ class ColorPoint extends Point {
``` ```
上面代码中子类的constructor方法没有调用super方法之前就使用this关键字结果报错而放在super方法之后就是正确的。 上面代码中子类的constructor方法没有调用super之前就使用this关键字结果报错而放在super方法之后就是正确的。
下面是生成子类实例的代码。 下面是生成子类实例的代码。
@ -318,7 +316,7 @@ cp instanceof Point // true
上面代码中实例对象cp同时是ColorPoint和Point两个类的实例这与ES5的行为完全一致。 上面代码中实例对象cp同时是ColorPoint和Point两个类的实例这与ES5的行为完全一致。
**2prototype属性** ### prototype属性
Class作为构造函数的升级也有自己的prototype属性其规则与ES5构造函数的prototype属性一致。 Class作为构造函数的升级也有自己的prototype属性其规则与ES5构造函数的prototype属性一致。
@ -346,7 +344,7 @@ C.prototype === Object
上面代码中子类的prototype属性都指向父类。如果一个类是基类即不存在任何继承那么它的原型指向`Function.prototype` 上面代码中子类的prototype属性都指向父类。如果一个类是基类即不存在任何继承那么它的原型指向`Function.prototype`
**3Object.getPrototypeOf方法** ### Object.getPrototypeOf()
Object.getPrototypeOf方法可以用来从子类上获取父类。 Object.getPrototypeOf方法可以用来从子类上获取父类。
@ -357,9 +355,9 @@ Object.getPrototypeOf(ColorPoint) === Point
``` ```
**4\__proto\__属性** ### \_\_proto\_\_属性
父类和子类的\__proto\__属性指向是不一样的。 父类和子类的\_\_proto\_\_属性指向是不一样的。
```javascript ```javascript
@ -371,12 +369,12 @@ p2.__proto__.__proto__ === p1.__proto__ // true
``` ```
通过子类的\__proto\__属性可以修改父类。 通过子类的\_\_proto\_\_属性可以修改父类。
```javascript ```javascript
p2.__proto__.__proto__.printName = function () { p2.__proto__.__proto__.printName = function () {
console.log('Ha'); console.log('Ha');
}; };
p1.printName() // "Ha" p1.printName() // "Ha"
@ -385,15 +383,15 @@ p1.printName() // "Ha"
上面代码在ColorPoint的实例p2上向Point类添加方法结果影响到了Point的实例p1。 上面代码在ColorPoint的实例p2上向Point类添加方法结果影响到了Point的实例p1。
**5构造函数的继承** ### 构造函数的继承
下面是一个继承原生的Array构造函数的例子。 下面是一个继承原生的Array构造函数的例子。
```javascript ```javascript
class MyArray extends Array { class MyArray extends Array {
constructor(...args) { constructor(...args) {
super(...args); super(...args);
} }
} }
@ -408,14 +406,14 @@ arr[1] = 12;
```javascript ```javascript
class MyError extends Error { class MyError extends Error {
} }
throw new MyError('Something happened!'); throw new MyError('Something happened!');
``` ```
### 取值函数getter和存值函数setter ## class的取值函数getter和存值函数setter
与ES5一样在Class内部可以使用get和set关键字对某个属性设置存值函数和取值函数。 与ES5一样在Class内部可以使用get和set关键字对某个属性设置存值函数和取值函数。
@ -442,7 +440,7 @@ inst.prop
上面代码中prop属性有对应的存值函数和取值函数因此赋值和读取行为都被自定义了。 上面代码中prop属性有对应的存值函数和取值函数因此赋值和读取行为都被自定义了。
### Generator方法 ## Class的Generator方法
如果某个方法之前加上星号(*就表示该方法是一个Generator函数。 如果某个方法之前加上星号(*就表示该方法是一个Generator函数。
@ -458,7 +456,7 @@ class Foo {
} }
} }
} }
for (let x of new Foo('hello', 'world')) { for (let x of new Foo('hello', 'world')) {
console.log(x); console.log(x);
} }
@ -469,7 +467,7 @@ for (let x of new Foo('hello', 'world')) {
上面代码中Foo类的Symbol.iterator方法前有一个星号表示该方法是一个Generator函数。Symbol.iterator方法返回一个Foo类的默认遍历器for...of循环会自动调用这个遍历器。 上面代码中Foo类的Symbol.iterator方法前有一个星号表示该方法是一个Generator函数。Symbol.iterator方法返回一个Foo类的默认遍历器for...of循环会自动调用这个遍历器。
### 静态方法 ## Class的静态方法
类相当于实例的原型所有在类中定义的方法都会被实例继承。如果在一个方法前加上static关键字就表示该方法不会被实例继承而是直接通过类来调用这就称为“静态方法”。 类相当于实例的原型所有在类中定义的方法都会被实例继承。如果在一个方法前加上static关键字就表示该方法不会被实例继承而是直接通过类来调用这就称为“静态方法”。
@ -500,7 +498,7 @@ class Foo {
return 'hello'; return 'hello';
} }
} }
class Bar extends Foo { class Bar extends Foo {
} }