[译]JavaScript ES6 class指南

媒介

EcmaScript 2015 (又称ES6)经由过程一些新的症结字,使类成为了JS中一个新的一等国民。然则目前为止,这些关于类的新症结字仅仅是建立在旧的原型体系上的
语法糖,所以它们并没有带来任何的新特征。不过,它使代码的可读性变得更高,而且为以后版本里更多面向对象的新特征打下了基本。

如许做的缘由是为了保证向后兼容性。也就是,旧代码能够在不做任何hack的情况下,与新代码同时运转。

定义类

让我们追念一下在ES5中定义一个类的体式格局。经由过程不是很经常运用的Object.defineProperty要领,我能够定义一些只读的属性。

function Vehicle(make, year) {
  Object.defineProperty(this, 'make', {
    get: function() { return make; }
  });

  Object.defineProperty(this, 'year', {
    get: function() { return year; }
  });
}

Vehicle.prototype.toString = function() {
  return this.make + ' ' + this.year;
}

var vehicle = new Vehicle('Toyota Corolla', 2009);

console.log(vehicle.make); // Toyota Corolla
vehicle.make = 'Ford Mustang';
console.log(vehicle.toString()) // Toyota Corolla 2009

很简朴,我们定义了一个有两个只读属性和一个自定义toString要领的Vehicle类。让我们在ES6中来做一样的事变:

class Vehicle {
  constructor(make, year) {
    this._make = make;
    this._year = year;
  }

  get make() {
    return this._make;
  }

  get year() {
    return this._year;
  }

  toString() {
    return `${this.make} ${this.year}`;
  }
}

var vehicle = new Vehicle('Toyota Corolla', 2009);

console.log(vehicle.make); // Toyota Corolla
vehicle.make = 'Ford Mustang';
console.log(vehicle.toString()) // Toyota Corolla 2009

上面两个例子中定义的类有一个差别的处所。我们为了享用新的get语法带来的优点,所以只是将makeyear定义成了一般的属性。这使它们能够被外部所转变。假如你确切须要一个严厉的私有属性,照样请继续运用defineProperty

类声明

在ES6中,有两个声明类的体式格局。第一种要领叫作 类声明,这也是我们在上述例子中运用的体式格局。

class Vehicle() {
}

有一个须要注重的处所是,类声明与函数声明差别,它不会被提拔(hoisted)。比方,以下的代码事情一般:

console.log(helloWorld());

function helloWorld() {
  return "Hello World";
}

然则,以下代码会抛出一个异常:

var vehicle = new Vehicle();

class Vehicle() {
}

类表达式

另一个定义类的体式格局叫做 类表达式。它与函数表达式的运转体式格局完整一样。一个类表达式能够是签字的也能够是匿名的。

var Vehicle = class {
}

var Vehicle = class VehicleClass {
  constructor() {
    // VehicleClass is only available inside the class itself
  }
}

console.log(VehicleClass); // throws an exception

静态要领

static症结字是ES6的另一个语法糖,它使静态要领声明也成为了一个一等国民。在ES5中,静态要领就像是组织函数的一个属性。

function Vehicle() {
  // ...
}

Vehicle.compare = function(a, b) {
  // ...
}

在运用了新的static症结字后:

class Vehicle {
  static compare(a, b) {
    // ...
  }
}

在底层,JavaScript所做的,也只是将这个要领增加为Vehicle组织函数的一个属性。值得注重的是,你也能够用一样的语法为类增加静态属性。

类继续

旧的原型继续偶然看起来让人异常头疼。ES6中新的extends症结字处理了这个题目。在ES5,我们是这么做的:

function Motorcycle(make, year) {
  Vehicle.apply(this, [make, year]);
}

Motorcycle.prototype = Object.create(Vehicle.prototype, {
  toString: function() {
    return 'Motorcycle ' + this.make + ' ' + this.year;
  }
});

Motorcycle.prototype.constructor = Motorcycle;

运用的新的extends症结字,看上去就清楚多了:

class Motorcycle extends Vehicle {
  constructor(make, year) {
    super(make, year);
  }

  toString() {
    return `Motorcycle ${this.make} ${this.year}`;
  }
}

super症结字也能够用于静态要领:

class Vehicle {
  static compare(a, b) {
    // ...
  }
}

class Motorcycle {
  static compare(a, b) {
    if (super.compare(a, b)) {
      // ...
    }
  }
}

super症结字

上一个例子也展现了新的super症结字的用法。当你想要挪用父类的函数时,这个症结字就显得非常好用。

在想要挪用父类的组织函数时,你能够简朴地将super症结字视作一个函数运用,如super(make, year)。关于父类的其他函数,你能够将super视作一个对象,如super.toString()。例子:

class Motorcycle extends Vehicle {
  toString() {
    return 'Motorcycle ' + super.toString();
  }
}

可被盘算的要领名

当在class中声明属性时,定义属性名时,你能够运用表达式。这个语法特征在一些ORM类库中将会异常盛行。例子:

function createInterface(name) {
  return class {
    ['findBy' + name]() {
      return 'Found by ' + name;
    }
  }
}

const Interface = createInterface('Email');
const instance = new Interface();

console.log(instance.findByEmail());

末了

在当前,运用class症结字来声明类,而不运用原型,取得的仅仅是语法上的上风。然则,这个是一个顺应新语法和新实践的好最先。JavaScript天天都在变得更好,而且经由过程class症结字,能够使种种东西更好得协助你。

原文地点

https://strongloop.com/strongblog/an-introduction-to-javascript-es6-classes/

    原文作者:菜菜蔡伟
    原文地址: https://segmentfault.com/a/1190000003097911
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞