JavaScript高级程序设计(第四版)--学习记录之对象、类与面向对象编程(下)

发布于:2024-07-02 ⋅ 阅读:(13) ⋅ 点赞:(0)

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()); // {}