您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

ES6+ Class

上一节我们主要回顾了在 ES5 中使用构造的方式实现类了,并说明了如何实现类的继承。从上一节的讲解中,构造去实现类的继承还是有诸多繁琐的地方的,我们需要考虑子类和的关系,继承中的细节都需要自己手动处理。本节我们将要学习 ES6 中的类的基本使用和类的继承。在学习本节我们需要明确的是,ES6 中的类是基于现有语法的原型实现的,并没有引入新的面相对象的模型。它的本质还是我们上节提到的构造,只是让我们更加方便地使用,是基于原型的继承的语法糖。

上节我们在实现类的时候说,类不能被执行只能 new 来创建实例,当时我们是在内部手动处理的。在 ES6 中天然这个特性:

class Animal { }
Animal();
// Uncaught TypeError: Class constructor Animal cannot be invoked without 'new'

上面的中我们定义了动物类,在控制台中让其执行,会看到如上的未捕获的类型:意思是在没有 new 的情况下是无法构造 Animal 的。使用 class 定义的类和使用构造定义类,在使用上是一样的,只是创建类的方式不一样。

上节我们知道如何创建实例上的和原型上的,那么使用 class 是怎么实现的呢?class 类提供了 constructor ,并在 new 的时候认执行,所以在 constructor 内部在 this 上绑定实例上的。而 原型上的则是在对象中直接即可,实例如下:

class Animal {
  constructor() {
    this.type = '鸟类'
  }
  eat() {}
}
var a = new Animal();
console.log(a.hasOwnProperty('type'));	// true
console.log(a.hasOwnProperty('eat'));		// false

另外,在 ES7 中 class 还提供了一种方式在实例上绑定,这种方式不需要 this,直接使用等号在 class 类中进行赋值。

class Animal {
  constructor() {
    this.type = '鸟类'
  }
  age='100'
  eat() {}
}
var a = new Animal();
console.log(a.hasOwnProperty('age'));	// true

需要注意的是,上面的等号赋值方式要在 ES7 的环境中才能执行。

当我们深入了解对象时我们就会知道的 getter 和 setter ,提供了 get 和 set 两个用于访问和设置。在 ES5 中有 Object.define 可以对对象的进行劫持,Vue2 的底层就是使用这个 API 实现的。当然 class 类其实也是对象,它也可以使用 get 的方式返回值。如下实例:

class Animal {
  constructor() {
    this.type = "鸟类";
    this._age = ;
  }
  get a() {
    return this._age;
  }

  set a(newValue) {
    this._age = newValue;
  }
}

var animal = new Animal();
console.log(animal.a); // 8
animal.a = ;
console.log(animal.a); // 10

上面中我们就使用了 get 和 set 去值和设置值。那我们思考问题,set 和 get 是自有还是原型上的呢?其实 get 和 set 还是 class 类上的,所以是原型上的。

console.log(a.hasOwnProperty('a'));	// false

ES6 提供了用于定义静态和的关键字 static ,静态时不需要实例化该类,所以就不能通过实例去,但可以使用类直接去。

静态通常用于为应用程序创建工具,下面我们来看长方形类,定义长方形面积的静态。

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  static getArea(r) {
    return r.width * r.height;
  }
}

const r = new Rectangle(, );

console.log(Rectangle.getArea(r));	// 50

在上节构造中的继承我们知道,子类的构造中,需要我们去手动执行父构造并绑定this,还需要将子类的构造的原型链执行的原型。ES6 中的继承非常简单,在创建子类时只需要使用关键字 extends 即可创建子类。

// :动物
class Animal {
  constructor(name) {
    this.name = name;
  }
  eat() {
    console.log(this.name + '会吃饭!');
  }
  static getAge() {
		console.log('' + this.name + '的年龄10岁了');
		return ;
  }
}

// 子类:具体的动物——狗
class Dog extends Animal {}

上面的中子类 Owl 继承了 Animal,那这个时候我们都继承了什么呢?从上面的学习中中有,this 上的,原型上的和静态。

var dog = new Dog('狗');

console.log('name:', dog.name);			// name: 狗
console.log('age:', Dog.getAge());	// age: 10
dog.eat();	// 狗会吃饭!

从上面打印的结果,我们知道,实例 dog 已经继承了 Animal 上的和。在中对 eat 的定义不明确,所以在子类中我们重写 eat 。

class Dog extends Animal {
  eat() {
    console.log(this.name + '会吃饭!');
  }
}
var dog = new Dog('狗');
dog.eat();	// 狗喜欢吃骨头!

super 是 class 中的关键字,可以理解是的别名,用于对象的父对象上的。一般 super 有两种情况:super 当做;一种是 super 当做的对象使用。

第一种情况下,super 关键字作为,它的作用是为了绑定 this。所以子类的构造必须执行一次 super。认情况下,类中不写 constructor 时,constructor 会执行 super, 并绑定 this 指向当前子类。

class A {}

class B extends A {
  constructor() {
    super();
  }
}

上节中我们在创建子类时就去执行了并绑定了this,上面中的 super 和 A.call(this) 是相同的。

第二种情况下,super 当作的对象来使用的,什么情况下会使用呢?当我们在子类中想使用的时可以使用 super 直接的即可。

class A {
  getCount() {
    return ;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.getCount()); // 7
  }
}

let b = new B();

本节主要学习了 ES6 中 class 类的使用和相关的知识点,需要明确的是 class 类就是语法糖,底层还是基于现有的原型对象的继承来实现的。所以要想深入理解 ES6 的 class 就需要对 ES5 中的构造有深入的理解,另外,我们可以使用 babel 进行转译,得到的就是使用构造来实现的。


联系我
置顶