类
ES6新引入class关键字具有正式定义类的能力。
类定义:类声明和类表达式。
// 类声明 class Person {} // 类表达式 const Animal = class {};
类定义与函数定义的不同:
1:函数声明可以提升,类定义不能
2:函数受函数作用域限制,类受块作用域限制
//提升与否 console.log(FunctionDeclaration); // FunctionDeclaration() {} function FunctionDeclaration() {} console.log(FunctionDeclaration); // FunctionDeclaration() {} console.log(ClassDeclaration); // ReferenceError: ClassDeclaration is not defined class ClassDeclaration {} console.log(ClassDeclaration); // class ClassDeclaration {} //作用域限制范围 function FunctionDeclaration() {} class ClassDeclaration {} } console.log(FunctionDeclaration); // FunctionDeclaration() {} console.log(ClassDeclaration); // ReferenceError: ClassDeclaration is not defined
类构造函数:constructor关键字用于在类定义块内部创建类的构造函数。
实例化,使用new调用类的构造函数会执行如下操作:
(1) 在内存中创建一个新对象。(2) 这个新对象内部的 [[Prototype]] 指针被赋值为构造函数的 prototype 属性。(3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。(4) 执行构造函数内部的代码(给新对象添加属性)。(5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。class Animal {} class Person { constructor() { console.log('person ctor'); } } class Vegetable { constructor() { this.color = 'orange'; } } let a = new Animal(); let p = new Person(); // person ctor let v = new Vegetable(); console.log(v.color); // orange
类继承:使用extends关键字,可以继承任何拥有[[Construct]]和原型的对象。
class Vehicle {} // 继承类 class Bus extends Vehicle {} let b = new Bus(); console.log(b instanceof Bus); // true console.log(b instanceof Vehicle); // true function Person() {} // 继承普通构造函数 class Engineer extends Person {} let e = new Engineer(); console.log(e instanceof Engineer); // true console.log(e instanceof Person); // true
super():
class Vehicle { static identify() { console.log('vehicle'); } } class Bus extends Vehicle { static identify() { super.identify(); } } Bus.identify(); // vehicle
super 只能在派生类构造函数和静态方法中使用
class Vehicle{ constructor() { super(); //SyntaxError:'super' keyword unexpected } }
不能单独引用 super 关键字,要么用它调用构造函数,要么用它引用静态方法
class Vehicle {} class Bus extends Vehicle { constructor() { console.log(super); // SyntaxError: 'super' keyword unexpected here } }
调用 super()会调用父类构造函数,并将返回的实例赋值给 this
class Vehicle {} class Bus extends Vehicle { constructor() { super(); console.log(this instanceof Vehicle); } } new Bus(); // true
super()的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入
class Vehicle { constructor(licensePlate) { this.licensePlate = licensePlate; } } class Bus extends Vehicle { constructor(licensePlate) { super(licensePlate); } } console.log(new Bus('1337H4X')); // Bus { licensePlate: '1337H4X' }
如果没有定义类构造函数,在实例化派生类时会调用 super(),而且会传入所有传 给派生类的参数
class Vehicle { constructor(licensePlate) { this.licensePlate = licensePlate; } } class Bus extends Vehicle {} console.log(new Bus('1337H4X')); // Bus { licensePlate: '1337H4X' }
在类构造函数中,不能在调用 super()之前引用 this
class Vehicle {} class Bus extends Vehicle { constructor() { console.log(this); } } new Bus(); // ReferenceError: Must call super constructor in derived class // before accessing 'this' or returning from derived constructor
如果在派生类中显式定义了构造函数,则要么必须在其中调用 super(),要么必须 在其中返回一个对象
class Vehicle {} class Car extends Vehicle {} class Bus extends Vehicle { constructor() { super(); } } class Van extends Vehicle { constructor() { return {}; } } console.log(new Car()); // Car {} console.log(new Bus()); // Bus {} console.log(new Van()); // {}