Introduction

上篇文章大致介绍了一些ES6的特性,以及如何在低版本浏览器中使用它们。本文是对class的详解。

译自Axel Rauschmayer的Classes in ECMAScript 6

另外,如果只是想测试ES6,可以到这个网站

Overview

借助class 我们可以写出这样的代码:

   class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
} class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y);
this.color = color;
}
toString() {
return super.toString() + ' in ' + this.color;
}
} let cp = new ColorPoint(25, 8, 'green');
cp.toString(); // '(25, 8) in green' console.log(cp instanceof ColorPoint); // true
console.log(cp instanceof Point); // true

Base classes

我们可以定义如下的class:

    class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}

我们可以像使用ES5标准中的constructor一样实例化class

    > var p = new Point(25, 8);
> p.toString()
'(25, 8)'

实际上,class还是用function实现的,并没有为js创造一个全新的class体系。

    > typeof Point
'function'

但是,与function相比,它是不能直接调用的,也就是说必须得new出来

    > Point()
TypeError: Classes can’t be function-called

另外,它不会像function一样会被hoisted(原因是语义阶段无法解析到extends的内容)

    foo(); // works, because `foo` is hoisted
function foo() {}
new Foo(); // ReferenceError
class Foo {}
    function functionThatUsesBar() {
new Bar();
} functionThatUsesBar(); // ReferenceError
class Bar {}
functionThatUsesBar(); // OK

与函数一样,class的定义表达式也有两种,声明形式、表达式形式。之前用的都是声明形式,以下是表达式式的:

    const MyClass = class Me {
getClassName() {
return Me.name;
}
};
let inst = new MyClass();
console.log(inst.getClassName()); // Me
console.log(Me.name); // ReferenceError: Me is not defined

Inside the body of a class definition

class定义体是只能包含方法,不能包含属性的(标准定义组织认为原型链中不应包含属性),属性被写在constructor中。以下是三种会用到的方法(constructor 、static method、 prototype method):

    class Foo {
constructor(prop) {
this.prop = prop;
}
static staticMethod() {
return 'classy';
}
prototypeMethod() {
return 'prototypical';
}
}
let foo = new Foo(123);

如下图([[Prototype]]代表着继承关系)当对象被new出来,拿的是Foo.prototype : Object分支,从而可以调prototype method



constructor,这个方法本身,代表了class

    > Foo === Foo.prototype.constructor
true

constructor有时被称为类构造器。相较于ES5,它可以调用父类的constructor(使用super())。

static methods。它们归属于类本身。

    > typeof Foo.staticMethod
'function'
> Foo.staticMethod()
'classy'

关于Getters and setters,它们的语法如下:

    class MyClass {
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
}
> let inst = new MyClass();
> inst.prop = 123;
setter: 123
> inst.prop
'getter'

方法名是可以动态生成的

    class Foo() {
myMethod() {}
} class Foo() {
['my'+'Method']() {}
} const m = 'myMethod';
class Foo() {
[m]() {}
}

增加了迭代器的支持,需要给方法前面加一个*

    class IterableArguments {
constructor(...args) {
this.args = args;
}
* [Symbol.iterator]() {
for (let arg of this.args) {
yield arg;
}
}
} for (let x of new IterableArguments('hello', 'world')) {
console.log(x);
} // Output:
// hello
// world

Subclassing

通过extends,我们可以继承其它实现constructor的函数或对象。需要注意一下,constructor与非constructor调用父类方法的途径是不同的。

    class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
} class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // (A)
this.color = color;
}
toString() {
return super.toString() + ' in ' + this.color; // (B)
}
}
> let cp = new ColorPoint(25, 8, 'green');
> cp.toString()
'(25, 8) in green' > cp instanceof ColorPoint
true
> cp instanceof Point
true

子类的原型就是它的父类

    > Object.getPrototypeOf(ColorPoint) === Point
true

所以,static method也被继承了

    class Foo {
static classMethod() {
return 'hello';
}
} class Bar extends Foo {
}
Bar.classMethod(); // 'hello'

static方法也是支持调用父类的。

   class Foo {
static classMethod() {
return 'hello';
}
} class Bar extends Foo {
static classMethod() {
return super.classMethod() + ', too';
}
}
Bar.classMethod(); // 'hello, too'

关于子类中使用构造器,需要注意的是,调用this之前,需要调用super()

    class Foo {}

    class Bar extends Foo {
constructor(num) {
let tmp = num * 2; // OK
this.num = num; // ReferenceError
super();
this.num = num; // OK
}
}

constructors是可以被显示覆盖(override)的。

    class Foo {
constructor() {
return Object.create(null);
}
}
console.log(new Foo() instanceof Foo); // false

如果基类中不显示定义constructor,引擎会生成如下代码

    constructor() {}

对于子类

    constructor(...args) {
super(...args);
}

The details of classes

  • 类名不能为eval 或者 arguments,不能有重复的类名,constructor不支持getter,setter。
  • classes不能像函数一样调用。
  • 原型方法不能用作构造器:
    class C {
m() {}
}
new C.prototype.m(); // TypeError

The details of subclassing

ES 6中,子类的使用方法如下:

    class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
···
} class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y);
this.color = color;
}
···
} let cp = new ColorPoint(25, 8, 'green');

原型链实现:

> const getProto = Object.getPrototypeOf.bind(Object);

> getProto(Point) === Function.prototype
true
> getProto(function () {}) === Function.prototype
true > getProto(Point.prototype) === Object.prototype
true
> getProto({}) === Object.prototype
true

最新文章

  1. 如果客户端禁用cookie,session还能使用吗?
  2. MVC中Action 过滤
  3. Odoo 中group domain的优化应用
  4. NEWS - InstallShield 2015 正式发布
  5. gcc/g++ 静态动态库 混链接.
  6. angular-tour 用户新手引导
  7. Java学习之道:空指针错误求解救????????????
  8. javaproject积累——java 反射 invoke
  9. win10下vagrant+centos7 rails虚拟开发机配置流程
  10. java IO(三):字符流
  11. SLAM入门之视觉里程计(3):两视图对极约束 基础矩阵
  12. 基于FPGA的16阶级联型iir带通滤波器实现
  13. openshift上使用devicemapper
  14. nowcoder 206A - Birthday - [最小费用最大流]
  15. ASP.NET Core 2 学习笔记(二)生命周期
  16. iOS网络加载图片缓存与SDWebImage
  17. [转]C艹中的各种const总结
  18. HDU 5651 组合+逆元
  19. UITableView的代理方法
  20. "回车"(carriage return)和"换行"(line feed)

热门文章

  1. hdu 6058
  2. Floyd算法(弗洛伊德算法) 百度百科
  3. CSS:CSS 颜色十六进制值
  4. web面试常见问题
  5. NodeJS REST API with MySQL and Express
  6. JAVA基础--JAVA 集合框架(泛型、file类)16
  7. HDU1597【二分瞎搞】
  8. C++两个类相互引用错误留影
  9. Zju1610 Count the Colors(lazy标记详解)
  10. 开源Html5+Websocket+Mqtt实时聊天室