22
一步,一步前進の一步

ES6深入浅出之Classes。翻译的同时乱加个人见解,强烈推荐阅读原作者的文章,言简意赅。es6-classes-in-depth

语法本质

JS 是基于原型的语言,那么ES6里的classes是什么东西?classes 是原型继承的语法糖------主要是用来勾引不太理解 JS 原型链语法的其他语言使用者。ES6有好多新的特性本质上就是语法糖,classes也不例外。我会向你证明 classes 是语法糖,因为classes 的语法很容易使用 ES5的语法实现出来,classes 并不是JS 语法的一个变革,它存在的目的仅仅是使原型继承变得简单。

ES5ES6的类实现对比

那么,我假设你已经很好的理解了原型继承的原理,毕竟你已经在阅读ES6这么高级的东西了。下面代码定义车的类,可被实例化,加油,移动。

function Car () {
  this.fuel = 0;
  this.distance = 0;
}

Car.prototype.move = function () {
  if (this.fuel < 1) {
    throw new RangeError('Fuel tank is depleted')
  }
  this.fuel--
  this.distance += 2
}

Car.prototype.addFuel = function () {
  if (this.fuel >= 60) {
    throw new RangeError('Fuel tank is full')
  }
  this.fuel++
}

使用下面的代码使车跑起来吧:

var car = new Car()
car.addFuel()
car.move()
car.move()
// <- RangeError: 'Fuel tank is depleted'

上面的代码都是 ES5,那么 ES6该如何实现呢?类声明的书写和对象的写法十分相似,花括号前面只多了 class Name,类方法我们将采用方法名简写的形式。contrustor 是构造函数,可在里面初始化我们想初始化的东西。

class Car {
  constructor () {
    this.fuel = 0
    this.distance = 0
  }
  move () {
    if (this.fuel < 1) {
      throw new RangeError('Fuel tank is depleted')
    }
    this.fuel--
    this.distance += 2
  }
  addFuel () {
    if (this.fuel >= 60) {
      throw new RangeError('Fuel tank is full')
    }
    this.fuel++
  }
}

需要强调的是:类和对象声明写起来是很像,但是在类中属性及方法间是不允许使用逗号分隔的,分号倒是没问题。

类静态方法

大多数情况下,类是有静态方法的。回想一下我们日常使用最多的数组,常见的实例方法有.filter.reduce.map,类方法有Array.isArray。ES5中添加类方法十分容易(类方法和静态方法是同一个东西):

// es5
function Car () {
  this.topSpeed = Math.random()
}
Car.isFaster = function (left, right) {
  return left.topSpeed > right.topSpeed
}

在 ES6的 class 语法中,我们可以使用static关键字修饰方法,进而得到静态方法。

class Car {
  constructor () {
    this.topSpeed = Math.random()
  }
  static isFaster (left, right) {
    return left.topSpeed > right.topSpeed
  }
}

那么既然说classes是语法糖,那我们同样可以使用如下方式实现静态方法:

class Car {
  constructor () {
    this.topSpeed = Math.random()
  }
}
Car.isFaster = (left, right) => {
    return left.topSpeed > right.topSpeed;
}

目前 ES6还不支持使用 static 来修饰属性,若想获得类的静态属性,该如何实现?请参考上面代码,给出答案,可以在评论区做答?
提供另一种思路使用 getset实现静态属性,try it.

类继承

classes不仅使类声明变得简单,它让继承变得更加可读,容易。ES6中的 extends支持从基类衍生出更具个性化的子类。众所周知,特斯拉较其他汽车比较省油,特斯拉是啥。那么,我们基于上面的 Car来实现Tesla类。下面的代码的意思是 Tesla 类继承 Car,并复写 Car 爸爸的 move 方法进而行驶更远的距离。

class Tesla extends Car {
  move () {
    super.move()
    this.distance += 4
  }
}

var car = new Tesla()
car.addFuel()
car.move()
console.log(car.distance)

关于继承,有一点需要特别注意,当子类想要实现特有的构造函数 constructor 时,首行必须使用 super(...)调用父类的构造函数,先得到父类的this作为自己的 this。此处的理论有一点点深,有机会再讲。

class Car {
  constructor (speed) {
    this.speed = speed
  }
}
class Tesla extends Car {
  constructor (speed) {
    // 不调用 super 的话,会报错
    super(speed * 2)
    // 做其他初始化工作 。。。
  }
}

知识点总结

  1. classes 只是语法糖,使类声明和继承书写变的容易
  2. 子类 constructor 要么有,要么首行调用super
  3. 静态方法static修饰
  4. 子类会覆盖父类的同名方法,但是可以使用 super.xxxx 方法调用父类方法。

一步本人作了个决定,把Nicolás Bevacqua es6-in-depth都给翻译了,如果侵权了我就立刻删除🤞。不知道该如何快速提高个人技能,人还懒。望大家监督,各位前辈给指条进步明路也可以。

原文ES6 Classes in Depth

🌚 前端学习QQ群: 538631558 🌚

【开发环境推荐】Cloud Studio 是基于浏览器的集成式开发环境,支持绝大部分编程语言,包括 HTML5、PHP、Python、Java、Ruby、C/C++、.NET 小程序等等,无需下载安装程序,一键切换开发环境。 Cloud Studio提供了完整的 Linux 环境,并且支持自定义域名指向,动态计算资源调整,可以完成各种应用的开发编译与部署。

亖混子
4.7k 声望2.4k 粉丝

自信、自洽、自在