资讯专栏INFORMATION COLUMN

[译]JavaScript ES6 class指南

CoderDock / 273人阅读

摘要:前言又称通过一些新的关键字,使类成为了中一个新的一等公民。类声明在中,有两个声明类的方式。在使用了新的关键字后在底层,所做的,也只是将这个方法添加为构造函数的一个属性。在想要调用父类的构造函数时,你可以简单地将关键字视作一个函数使用,如。

前言

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://www.ucloud.cn/yun/85895.html

相关文章

  • []JavaScript ES6解构赋值指南

    摘要:解构赋值允许我们将右边的表达式看起来也像变量声明一般,然后在左边将值一一提取。数组的解构赋值现在假设我们有一个变量,其值为。通过,这会看上去更清晰简洁最后的解构赋值给的语法带来了更多的现代化。 前言 让我们来仔细地看看ES6所带来的更清晰的变量声明与赋值语法。现今的变量声明语法十分的直接:左边是一个变量名,右边可以是一个数组:[]的表达式或一个对象:{}的表达式,等等。解构赋值允许我...

    Jeff 评论0 收藏0
  • []JavaScript ES6迭代器指南

    摘要:前言又称提供一个全新的迭代器的概念,它允许我们在语言层面上定义一个有限或无限的序列。后者可以被用来帮助我们理解迭代器。但是当我们使用迭代器时,这个问题就迎刃而解了。是中的新语法,用来配合迭代器。这是因为数组的迭代器只返回其中预期的元素。 前言 EcmaScript 2015 (又称ES6)提供一个全新的迭代器的概念,它允许我们在语言层面上定义一个(有限或无限的)序列。 暂时先抛开它...

    daryl 评论0 收藏0
  • []JavaScript ES6箭头函数指南

    摘要:以下例子的目的是使用来展示一个每秒都会更新的时钟当尝试在的回调中使用来引用元素时,很不幸,我们得到的只是一个属于回调函数自身上下文的。 前言 胖箭头函数(Fat arrow functions),又称箭头函数,是一个来自ECMAScript 2015(又称ES6)的全新特性。有传闻说,箭头函数的语法=>,是受到了CoffeeScript 的影响,并且它与CoffeeScript中的=>...

    makeFoxPlay 评论0 收藏0
  • [] 从 CoffeeScript 迁移到 ES6

    摘要:语法校验会给出警告当你仍在使用或不通过任何关键字声明变量时。但是如果脚本中还有其他的普通导出,就会得到非常奇怪的结果这个坑爹的情况目前还没有任何好的解决方案。 我在多年前爱上了coffeScript。对于javaScript,我一直保持着深沉的爱,也十分高兴得看到node.js的快速发展,但是作为一个有python背景的程序员,我更喜欢coffeeScript的简练语法。 在任何一个活...

    刘东 评论0 收藏0
  • []JavaScript ES6模块指南

    摘要:模块可以导入和导出各种类型的变量,如函数,对象,字符串,数字,布尔值,等等。所以这可能会导致一些不符合预期的行为。可变的基本类型值在导入一些基本类型的值如数字,布尔值或字符串时,可能会产生一个有趣的副作用。 前言 ECMAScript 2015(又称ES6)提供了一个前端JavaScript缺失已久的特性 —— 模块。ES2015中的模块参考了CommonJS规范(目前Node.js的...

    yimo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<