类是什么
Es6 新增的类其实就是基于原型机制的语法糖,类的语法可以让开发者更好的定义向后兼容的类,不仅可以继承内置类型,还可以继承自定义类型。
如何定义类
定义类有俩种主要方式:类声明和类表达式,这俩种方式都使用 class 关键字和大花括号。与构造函数一样,编程风格建议类名的首字母大写。程序员约定俗成的。
//类声明 class Person {}; //表达式类 const Animal = class {};
复制代码
注意:在类里面函数声明(Var)不能提升作用域,而且类受块作用域限制。
类与构造函数区别
调用类构造函数必须使用 new 操作符,而普通构造函数如果不使用 new 调用,就会以全局的 this(window)作为内部对象。调用类构造函数时如果不使用 new 就会抛出错误。
class Person {};
function Person1(){};
let p = Person();//Uncaught TypeError: Class constructor Person cannot be invoked without 'new'at
let p1 = Person1();
复制代码
迭代器和生成器方法
类定义语支持在原型和类本身上定义生成器方法。
class Person {
//在原型上定义生成器
*nameIterator (){
yield 'jackson';
yield 'bear';
}
//在类上定义生成器
static *colorIterator(){
yield 'blue';
yield 'green';
}
};
//类
let p = new Person();
let names = p.nameIterator();
console.log(names.next().value);//jackson
console.log(names.next().value);//bear
//原型
let colors = Person.colorIterator();
console.log(colors.next().value);//blue
console.log(colors.next().value);//green
复制代码
类的继承
Es6 新特性中比较出色的就是原生支持类继承机制,虽然类继承是使用的新语法,但是依据的还是原型链
1. 继承基础
Es6 支持单继承,使用 extends 关键字,就可以继承任何拥有 construct 和原型对象。这不仅可以继承一个类,也可以继承普通的构造函数。
class Exten {};
//继承类
class Bus extends Exten {};
let a = new Bus();
console.log(a instanceof Bus); //true
console.log(a instanceof Exten); //true
function Person(){};
//继承普通构造函数
class Eng extends Person {};
let b = new Eng();
console.log(b instanceof Eng); //true
console.log(b instanceof Person); //true
复制代码
2.构造函数、HomeObject、Super
派生类的方法可以通过 super 关键字来引用他们的原型,(super 只能在派生类中使用)。在类构造函数中使用 super 可以调用父类构造函数。
class Vehicle {
constructor() {
this.hasEngine = true;
}
}
class Bus extends Vehicle {
constructor() {
// 不要在调用 super()之前引用 this,否则会抛出 ReferenceError
super(); // 相当于 super.constructor()
console.log(this instanceof Vehicle); // true
console.log(this); // Bus { hasEngine: true }
}
}
new Bus();
复制代码
注意 ES6 给类构造函数和静态方法添加了内部特性 HomeObject,这个特性是一个指针,指向定义该方法的对象。这个指针是自动赋值的,而且只能在 JavaScript 引擎内部 访问。super 始终会定义为 HomeObject 的原型。
使用 super 要注意的问题
super 只能在派生类构造函数和静态方法中使用。
不能单独引用 super 关键字,要么用它调用构造函数,要么用它引用静态方法。
调用 super()会调用父类构造函数,并将返回的实例赋值给 this。
super()的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入。
如果没有定义类构造函数,在实例化派生类时会调用 super(),而且会传入所有传给派生类的参数。
在类构造函数中,不能在调用 super()之前引用 this。
如果在派生类中显式定义了构造函数,则要么必须在其中调用 super(),要么必须在其中返回一个对象。
3.继承内置类型
Es6 为类继承内置引用类型提高了比较流程的机制,我们可以更方便扩展内置类型。 我们写一个去掉偶数。
class SuperArray extends Array {}
let a1 = new SuperArray(1, 2, 3, 4, 5);
let a2 = a1.filter(x => !!(x % 2))
console.log(a1); // [1, 2, 3, 4, 5]
console.log(a2); // [1, 3, 5]
console.log(a1 instanceof SuperArray); // true
console.log(a2 instanceof SuperArray); // true
复制代码
Es6 的 Class 绝大部分功能,ES5 都可以做到,但是新的 class 写法只是让语法更加清晰,更像面向对象编程的语法。
评论