JavaScript 语言中,生成实例对象的传统办法是通过构造函数

class Point {  // ...}typeof Point // "function"Point === Point.prototype.constructor // true

下面代码表明,类的数据类型就是函数,类自身就指向构造函数
应用的时候,也是间接对类应用new命令,跟构造函数的用法完全一致。

类的实例对象

class Bar {  doStuff() {    console.log('stuff');  }}var b = new Bar();b.doStuff() // "stuff"

构造函数的prototype属性,在 ES6 的“类”下面持续存在。事实上,类的所有办法都定义在类的prototype属性下面。

class Point {  constructor() {    // ...  }  toString() {    // ...  }  toValue() {    // ...  }}// 等同于Point.prototype = {  constructor() {},  toString() {},  toValue() {},};

在类的实例下面调用办法,其实就是调用原型上的办法。
类必须应用new调用,否则会报错。这是它跟一般构造函数的一个次要区别,后者不必new也能够执行。

与 ES5 一样,类的所有实例共享一个原型对象。

var p1 = new Point(2,3);var p2 = new Point(3,2);p1.__proto__ === p2.__proto__//true

下面代码中,p1和p2都是Point的实例,它们的原型都是Point.prototype,所以__proto__属性是相等的。

这也意味着,能够通过实例的__proto__属性为“类”增加办法。

proto 并不是语言自身的个性,这是各大厂商具体实现时增加的公有属性,尽管目前很多古代浏览器的 JS 引擎中都提供了这个公有属性,但仍旧不倡议在生产中应用该属性,防止对环境产生依赖。生产环境中,咱们能够应用 Object.getPrototypeOf 办法来获取实例对象的原型,而后再来为原型增加办法/属性。

var p1 = new Point(2,3);var p2 = new Point(3,2);p1.__proto__.printName = function () { return 'Oops' };p1.printName() // "Oops"p2.printName() // "Oops"var p3 = new Point(4,2);p3.printName() // "Oops"

下面代码在p1的原型上增加了一个printName办法,因为p1的原型就是p2的原型,因而p2也能够调用这个办法。而且,尔后新建的实例p3也能够调用这个办法。这意味着,应用实例的__proto__属性改写原型,必须相当审慎,不举荐应用,因为这会扭转“类”的原始定义,影响到所有实例

Class表达式
与函数一样,类也能够应用表达式的模式定义。

const MyClass = class Me {  getClassName() {    return Me.name;  }};

下面代码应用表达式定义了一个类。须要留神的是,这个类的名字是MyClass而不是Me,Me只在 Class 的外部代码可用,指代以后类。

let inst = new MyClass();inst.getClassName() // MeMe.name // ReferenceError: Me is not defined

下面代码示意,Me只在 Class 外部有定义。
如果类的外部没用到的话,能够省略Me,也就是能够写成上面的模式。
const MyClass = class { / ... / };
采纳 Class 表达式,能够写出立刻执行的 Class。

let person = new class {  constructor(name) {    this.name = name;  }  sayName() {    console.log(this.name);  }}('张三');person.sayName(); // "张三"

下面代码中,person是一个立刻执行的类的实例。

不存在变量晋升
类不存在变量晋升(hoist),这一点与 ES5 齐全不同。ES6 不会把类的申明晋升到代码头部。这种规定的起因与下文要提到的继承无关,必须保障子类在父类之后定义。

附件下载:http://github.crmeb.net/u/defu