《深入理解ES6》阅读随笔
extends
在 ES6 中,可以使用 extends 关键字来实现继承的功能,如下所示,Animal 是 Cat 的基类,Cat 是 Animal 的派生类,Cat 继承了 Animal 的基本能力:
class Animal {
constructor(name) {
this.name = name;
}
canRun() {
console.log(`${this.name} can run!`);
}
}
class Cat extends Animal {
canSay() {
console.log(`${this.name} can say miao~`);
}
}
const cat = new Cat("Tom");
cat.canRun(); // Tom can run!
cat.canSay(); // Tom can say miao~
类方法遮蔽
在派生类中重复定义函数会覆盖掉基类中的原始函数:
class Animal {
constructor(name) {
this.name = name;
}
canRun() {
console.log(`${this.name} can run!`);
}
}
class Cat extends Animal {
canRun() {
console.log(`${this.name} can run,too!`);
}
}
const cat = new Cat("Tom");
cat.canRun(); // Tom can run,too!
静态成员继承
基类中的静态成员同样可以继承到派生类中:
class Animal {
constructor(name) {
this.name = name;
}
canRun() {
console.log(`${this.name} can run!`);
}
static canEat() {
console.log(`${this.name} can eat!`);
}
}
class Cat extends Animal {}
const cat = new Cat("Tom");
cat.canRun(); // Tom can run!
Animal.canEat() // Animal can eat!
Cat.canEat() // Cat can eat!
派生自表达式的类
基于表达式可以灵活的派生新类:
function Animal(name) {
this.name = name;
}
Animal.prototype.canRun = function () {
console.log(`${this.name} can run!`);
};
function getBase() {
return Animal;
}
class Cat extends getBase() {}
const cat = new Cat("Tom");
cat.canRun(); // Tom can run!
内建对象的继承
像 Array 这类内建对象,在之前 ES5 中是很难实现继承的,但是在 ES6 中可以很顺利的实现:
class MyArray extends Array {}
const myArray = new MyArray();
myArray[0] = 10;
console.log(myArray); // MyArray [ 10 ]
myArray.length = 0;
console.log(myArray); // MyArray []
Symbol.species
Symbol.species 被用于返回函数的静态访问器属性:
class MyArray1 extends Array {}
const myArray1 = new MyArray1();
const sliceFunc1 = myArray1.slice();
console.log("******** myArray1 ********");
console.log(myArray1 instanceof MyArray1); // true
console.log(myArray1 instanceof Array); // true
console.log(sliceFunc1 instanceof MyArray1); // true
class MyArray2 extends Array {
static get [Symbol.species]() {
return Array;
}
}
const myArray2 = new MyArray2();
const sliceFunc2 = myArray2.slice();
console.log("******** myArray2 ********");
console.log(myArray2 instanceof MyArray2); // true
console.log(myArray2 instanceof Array); // true
console.log(sliceFunc2 instanceof MyArray2); // false
在上面的例子中,myArray1 在继承 Array 以后,在不做任何操作的情况下,其 slice() 也会返回 MyArray1 的实例;然而我们在 myArray2 中,做了一些干预,让其 slice() 方法只返回 Array 的实例。
new.target 的应用
使用 new.target 可以判断是哪个类进行了实例化,基于此,可以对基类和派生类分别进行处理:
class Animal {
constructor(name) {
this.name = name;
// 阻止基类的实例化
if (new.target === Animal) {
throw new Error("Can not create animal directly!");
}
}
canRun() {
console.log(`${this.name} can run!`);
}
}
class Cat extends Animal {
constructor() {
super();
if (new.target === Cat) {
console.log("That is Ok!");
}
}
}
const cat = new Cat("Tom"); // That is Ok!
const animal = new Animal("Tom"); // Error: Can not create animal directly!
网友评论