认识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()