1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-25 19:22:21 +00:00

edit class

This commit is contained in:
Ruan Yifeng 2015-04-08 19:43:27 +08:00
parent eb5b1f07a9
commit 2615c4bcc8

View File

@ -19,7 +19,7 @@ Point.prototype.toString = function () {
```
ES6引入了Class这个概念作为对象的模板。通过class关键字可以定义类。基本上class可以看作只是一个语法糖它的绝大部分功能ES5都可以做到新的class写法只是让对象原型的写法更加清晰而已。上面的代码用“类”改写就是下面这样。
ES6引入了Class这个概念作为对象的模板。通过class关键字可以定义类。基本上class可以看作只是一个语法糖它的绝大部分功能ES5都可以做到新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用“类”改写,就是下面这样。
```javascript
@ -39,7 +39,20 @@ class Point {
```
上面代码定义了一个“类”可以看到里面有一个constructor方法这就是构造方法而this关键字则代表实例对象。Point类除了构造方法还定义了一个toString方法。注意定义方法的时候前面不需要加上function这个保留字直接把函数定义放进去了就可以了。
上面代码定义了一个“类”可以看到里面有一个constructor方法这就是构造方法而this关键字则代表实例对象。也就是说ES5的构造函数Point对应ES6的Point类的构造方法。
Point类除了构造方法还定义了一个toString方法。注意定义方法的时候前面不需要加上function这个保留字直接把函数定义放进去了就可以了。ES5的`Point.prototype`在ES6继续存在也就是说除了constructor方法以外类的方法都定义在类的prototype属性上面。
```javascript
Point.prototype.constructor === Point // true
Point.prototype.toString
// function toString() {
// return '(' + this.x + ', ' + this.y + ')';
// }
```
**2constructor方法**
@ -100,7 +113,7 @@ class Point {
}
var point = Point(2, 3);
var point = new Point(2, 3);
point.toString() // (2, 3)
@ -142,7 +155,7 @@ p3.printName() // "Oops"
```
上面代码在p1的原型上添加了一个printName方法由于p1的原型就是p2的原型因此p2也可以调用这个方法。而且此后新建的实例p3也可以调用这个方法。这意味着使用实例的\__proto\__属性改写原型必须相当谨慎不推荐使用因为这会改变Class的原始定义影响到所有实例。
上面代码在p1的原型上添加了一个printName方法由于p1的原型就是p2的原型因此p2也可以调用这个方法。而且此后新建的实例p3也可以调用这个方法。这意味着使用实例的\_\_proto\_\_属性改写原型必须相当谨慎不推荐使用因为这会改变Class的原始定义影响到所有实例。
**4name属性**
@ -261,7 +274,7 @@ class ColorPoint extends Point {
class Point { /* ... */ }
class ColorPoint extends Foo {
class ColorPoint extends Point {
constructor() {
}
}
@ -316,33 +329,99 @@ cp instanceof Point // true
上面代码中实例对象cp同时是ColorPoint和Point两个类的实例这与ES5的行为完全一致。
### prototype属性
### 类的prototype属性和\_\_proto\_\_属性
Class作为构造函数的升级也有自己的prototype属性其规则与ES5构造函数的prototype属性一致。
在ES5中每一个对象都有\_\_proto\_\_属性指向对应的构造函数的prototype属性。Class作为构造函数的语法糖也有自己的prototype属性和\_\_proto\_\_属性因此同时存在两条继承链。
- 子类的\_\_proto\_\_属性表示构造函数的继承总是指向父类
- 子类prototype属性的\_\_proto\_\_属性表示方法的继承总是指向父类的prototype属性
```javascript
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
```
上面代码中子类A的`__proto__`属性指向父类B子类A的prototype属性的__proto__属性指向父类B的prototype属性。
第一条继承链,实质如下。
```javascript
class B extends A {
constructor() {
return A.call(this);
}
}
// 等同于
class B extends A {
constructor() {
return B.__proto__.call(this);
}
}
```
第二条继承链,实质如下。
```javascript
B.prototype = new A();
// 等同于
B.prototype.__proto__ = A.prototype;
```
此外,还有三种特殊情况。
```javascript
class A extends Object {
}
A.__proto__ === Object // true
A.prototype.__proto__ === Object.prototype // true
```
第一种特殊情况子类A继承Object。这种情况下A其实就是构造函数Object的复制A的实例就是Object的实例。
```javascript
class A {
}
A.prototype === Function.prototype
// true
class B extends A {
}
B.prototype === A
// true
class C extends Object {
}
C.prototype === Object
// true
A.__proto__ === Function.prototype // true
A.prototype.__proto__ === Object.prototype // true
```
上面代码中子类的prototype属性都指向父类。如果一个类是基类即不存在任何继承那么它的原型指向`Function.prototype`
第二种特殊情况A作为一个基类即不存在任何继承就是一个普通函数所以直接继承`Funciton.prototype`。但是A调用后返回一个空对象即Object实例所以`A.prototype.__proto__`指向构造函数Object的prototype属性。
```javascript
class A extends null {
}
A.__proto__ === Function.prototype // true
A.prototype.__proto__ === null // true
```
第三种特殊情况与第二种情况非常像。A也是一个普通函数所以直接继承`Funciton.prototype`。但是A调用后返回的对象不继承任何方法所以它的`__proto__`指向`Function.prototype`,即实质上执行了下面的代码。
```javascript
class C extends null {
constructor() { return Object.create(null); }
}
```
### Object.getPrototypeOf()
@ -355,7 +434,7 @@ Object.getPrototypeOf(ColorPoint) === Point
```
### \_\_proto\_\_属性
### 实例的\_\_proto\_\_属性
父类和子类的\_\_proto\_\_属性指向是不一样的。
@ -508,6 +587,26 @@ Bar.classMethod(); // 'hello'
上面代码中父类Foo有一个静态方法子类Bar可以调用这个方法。
静态方法也是可以从super对象上调用的。
```javascript
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
static classMethod() {
return super.classMethod() + ', too';
}
}
Bar.classMethod();
```
## Module
ES6的Class只是面向对象编程的语法糖升级了ES5的对象定义的写法并没有解决模块化问题。Module功能就是为了解决这个问题而提出的。