ES6相关知识——class

77 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

class定义类

实际上,类是“特殊的函数 ,就像你能够定义的函数表达式函数声明一样,类语法有两个组成部分:类表达式类声明

本质依旧是构造函数、原型链的语法糖

//  类的声明
class Person { }
// 类似于:
function Person { }

// 还有一个:类的表达式(但不常用)
var a = class {}

注意:函数声明类声明之间的一个重要区别在于,函数声明会提升,类声明不会。你首先需要声明你的类,然后再访问它(类表达式也是先声明后访问)

类的特性(和构造函数是一样的)

  1. 有显示原型prototype,也有隐式原型__proto__,还有constructor
  2. 通过typeof操作 类 打印出来的是 function而不是 class

class的构造方法

类的作用在于构建对象,而constructor是一种用于创建和初始化class创建的对象的特殊方法。
一个类只能有一个构造函数 (多个会报错)

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
}
var p = new Person("a", 18)

如果不指定一个构造函数 (constructor) 方法,则使用一个默认的构造函数 (constructor)。

类的普通实例方法

一般通过创建出来的对象进行访问

类的实例方法定义:在class里定义方法相当于在原型上定义

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  eating() {
    console.log(this.name + " eating~")
  }
}
var p = new Person("a", 18)
p.eating()

类的访问器方法定义:在class中定义 getter 和 setter 函数

class Person {
  constructor() {
    this._address = "广州市"
  }
  // 类的访问器方法
  get address() {
    console.log("拦截访问操作")
    return this._address
  }

  set address(newAddress) {
    console.log("拦截设置操作")
    this._address = newAddress
  }
}

类的静态方法

static 关键字用来定义一个类的一个静态方法。
通过类名进行访问,不用创建实例
通常用于为一个应用程序创建工具函数。

class Foo {
    static displayName = "Point";
    static classWrite() {
        console.log("hello world!");
    }
    classWrite() {
        console.log("你好,世界!");
    }
}

const p1 = new Foo();
console.log(p1.displayName) // undefined
Foo.classWrite();// hello world!

如果在实例上调用静态方法,就会抛出错误,表示该方法不存在。

因为静态方法只能通过类来调用,实例无法继承它的方法。

所以说如果静态方法中包含 this 关键字,通过类调用则这个 this 指向的是类,而不是实例。


在前面的文章可以看出我们实现继承是很麻烦的,但用class来实现继承很简单

用class实现继承


使用 extends 关键字在 类声明类表达式 中创建一个类作为另一个类的一个子类。
以前传参数给父类我们使用的是call 方法,现在则要使用super关键字(语法要求,不使用会报错)
super的使用:调用 父类 的构造函数并传参、调用 父类 上的方法

class Person {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}
// Student称之为子类(派生类)
class Student extends Person {  // Student 继承 Person
   constructor(name) {
    super(name); // 调用父类构造函数并传入 name 参数
  }

  speak() {
    console.log(`${this.name} barks.`);
  }
}

var p = new Student('a');
p.speak();// 'a barks.'

子类可以继承父类的方法,但如果子类重写了父类的方法,则打印的时候会输出子类重写后的方法

🚨注意:在子(派生)类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数。

ES6转ES5的代码(了解)

因为有一些较低版本的浏览器不能识别比较新的语法,所以我们要将它转成ES5从而让浏览器识别(使用babel工具可以将新的JS/TS代码转成ES5的代码)

继承内置类

继承系统的类并对其进行扩展

以array为例:

class MyArray extends Array {
  eating(){
    console.log("eatting~")
  }
}

const a = new MyArray(1, 2, 3);
const b = a.map(x => x);  // MyArray 继承了 Array 的方法,可以使用map方法

b instanceof MyArray; // true 
console.log(b); // MyArray(3) [ 1, 2, 3 ]
console.log(a.eating); // [Function: eating]

类的混入mixin

因为JavaScript的类只支持单继承,即只能继承一个父类
但我们想要继承多个父类,则该功能必须由父类提供

一个以超类作为输入的函数和一个继承该超类的子类作为输出可以用于在 ECMAScript 中实现混合:

function mixinRunner(BaseClass) {
  class NewClass extends BaseClass {  // 可以指定类的名称
    running() {
      console.log("running~")
    }
  }
  return NewClass
}

function mixinEater(BaseClass) {
  return class extends BaseClass {  // 也可以不指定类的名称
    eating() {
      console.log("eatting~")
    }
  }
}

class Person { }
class Student extends mixinEater(mixinRunner(Person)) {}
var p = new Student()
p.running() // running~
p.eating() // eatting~

在上述代码中,虽然没有mixin关键字,但我们利用JS原有的特性来实现混入的效果。

参考资料:
MDN
babel在线网站:babeljs.io/
coderwhy 的JS高级课程