JavaScript|Class定义类

认识class和class的构造函数

在之前我讲原型的文章中,按构造函数创建的类不仅和普通的函数相似,还不容易理解。在ES6中,我们可以使用class来定义类,class的本质其实是构造函数的语法糖而已。

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(`${this.name} is ${this.age} years old.`);
  }
}

var person = new Person('Tom', 18);

person.say(); // Tom is 18 years old.

console.log(person); // Person { name: 'Tom', age: 18 }
console.log(person.__proto__); // {}

在Babel中会被转换成构造函数的代码,如下:

var Person = /*#__PURE__*/function () {
  function Person(name, age) {
    this.name = name;
    this.age = age;
  }

  var _proto = Person.prototype;

  _proto.say = function say() {
    console.log(this.name + " is " + this.age + " years old.");
  };

  return Person;
}();

var person = new Person('Tom', 18);
person.say(); // Tom is 18 years old.

class方法和方法拦截

class中的方法可以通过静态方法来实现,也可以通过实例方法来实现。

var names = ["abc", "cba", "nba"]

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
    this._address = "广州市"
  }

  // 普通的实例方法
  // 创建出来的对象进行访问
  // var p = new Person()
  // p.eating()
  eating() {
    console.log(this.name + " eating~")
  }

  running() {
    console.log(this.name + " running~")
  }

  // 类的访问器方法
  get address() {
    console.log("拦截访问操作")
    return this._address
  }

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

  // 类的静态方法(类方法)
  // Person.createPerson()
  static randomPerson() {
    var nameIndex = Math.floor(Math.random() * names.length)
    var name = names[nameIndex]
    var age = Math.floor(Math.random() * 100)
    return new Person(name, age)
  }
}

var p = new Person("Ricky", 18)
p.eating() // Ricky eating~
p.running() // Ricky running~

console.log(p.address) // 拦截访问操作 // 广州市
p.address = "北京市" // 拦截设置操作
console.log(p.address) // 拦截访问操作 // 北京市

// console.log(Object.getOwnPropertyDescriptors(Person.prototype))

for (var i = 0; i < 50; i++) {
  console.log(Person.randomPerson()) // Person { name: 'cba', age: 52, _address: '广州市' } ... x100
}

class中的继承

在ES6中新增extends关键字,可以方便的帮助我们实现继承。

还有super关键字,这个super关键字有不同的使用方式:注意:在子(派生)类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数!super的使用位置有三个:子类的构造函数、实例方法、静态方法。

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }

  say() {
    console.log(this.name + " is " + this.age + " years old.")
  }
}

class Student extends Person {
  constructor(name, age, grade) {
    super(name, age)
    this.grade = grade
  }
  say() {
    super.say()
    console.log("I am a student. My grade is " + this.grade)
  }
}

var s = new Student("Ricky", 18, "一年级")

s.say() // Ricky is 18 years old. I am a student. My grade is 一年级

继承内置类型

可以通过继承内置类型来实现继承,如下:


class superArray extends Array {
    lastItem() {
        return this[this.length - 1]
    }
}

var arr = new superArray(1, 2, 3)
console.log(arr.lastItem()) // 3

类的混入

混入是一种特殊的继承,它可以将多个类的特性混入到目标类中。

class Person {

}

function mixinRunner(BaseClass) {
  class NewClass extends BaseClass {
    running() {
      console.log("running~")
    }
  }
  return NewClass
}

function mixinEater(BaseClass) {
  return class extends BaseClass {
    eating() {
      console.log("eating~")
    }
  }
}

// 在JS中类只能有一个父类: 单继承
class Student extends Person {

}

var NewStudent = mixinEater(mixinRunner(Student))
var ns = new NewStudent()
ns.running()
ns.eating()