红宝书阅读笔记!第十八天_类

614 阅读5分钟

ECMAScript6 新引入了class关键字具有正式定义类的能力。类(class)是ECMAScript中新的基础性语法糖结构。但是类背后使用的仍然是原型和构造函数的概念。

类定义

与函数相似,定义类也有两种方式:类声明和类表达式。这两种方式都是用class关键字加大括号:

//类声明
class Person {}

//类表达式
const Animal = class {};

类要先声明后使用。

类的构成

类可以包含构造函数方法、实例方法、获取函数、设置函数和静态类方法,但这都不是必须的。空的类定义一样有效。默认情况下,类定义中的代码都在严格模式下执行。

与函数构造函数一样,多数编程风格都建议类名的首字母要大写,以区别与通过他创建的实例。

类表达式的名称是可选的。在把类表达式赋值给变量后,可以通过name属性取得类表达式的名称字符串。但不能在类表达式作用域外部访问这个标识符。

类构造函数

constructor关键字用于在类定义块内部,创建类的构造函数。方法名constructor会告诉解释器在使用new操作符创建类的新实例时,应该调用这个函数。构造函数的定义不是必须的,不定义构造函数相当于将构造函数定义为空函数。

1.实例化

使用new操作符实例化Person的操作等于使用new调用其构造函数。唯一可感知的不同之处在于,JavaScript解释器知道使用new和类意味着应该使用constructor函数进行实例化。

使用new调用类的构造函数会执行如下操作。

①在内存中创建一个对象。

②这个对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性。

③构造函数内部的this被赋值为这个新对象。

④执行构造函数的内部的代码。

⑤如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

类实例化时传入的参数会用作构造函数的参数。如果不需要参数,则类名后面的括号也是可选的

class Person{
	constructor(name){
    	console.log(arguments.length);
        this.name = name || null;
    }
}

let p1 = new Person;
console.log(p1.name);

let p2 = new Person('Jake');
console.log(p2.name);

构造函数会在执行后返回this对象,构造函数返回的对象会被用作实例化的对象,如果用不到,就会被销毁。

类构造函数与构造函数的主要区别是,调用类构造函数必须使用new操作符。而普通构造函数如果不适用new调用,那么就会以全局的this(通常是window)作为内部对象。

2.把类当成特殊函数

ECMAScript中没有正式的类这个类型。

类标识符有prototype属性,而这个原型也有一个constructor属性指向类本身👇

与普通构造函数一样,可以使用instanceof操作符来检查构造函数原型是否存在于实例的原型链中。

类是JavaScript的一等公民,因此可以像其他对象或函数引用一样把类作为参数传递:

类可以像函数在任何地方定义,比如在数值中,类也可以立即实例化

实例、原型和类成员

类的语法可以非常方便地定义应该存在于实例上的成员、应该存在于原型上的成员,以及应该存在于类本身的成员。

1.实例成员

每次通过new调用类标识符时,都会执行类构造函数。在这个函数内部,可以为新创建的实例,添加“自有”属性。在构造完毕后,仍然可以给实力继续添加新成员。

每个实例都对应一个唯一的成员对象,这意味着所有成员都不会再原型上共享

2.原型方法和访问器

为了在实例间共享方法,类 定义语法把在块中定义的方法作为原型方法。

添加在this上的所有内容都会存在于不同的实例上。

在类块中定义的所有内容都会定义在类的原型上。

类定义也支持获取和设置访问器👇

class Person{
    set name(newName){
    	this.name_ = newName;
    }
    
    get name(){
    	return this.name_;
    }
}

3.静态类方法

可以在类上定义静态方法。

静态成员在类定义中使用static关键字作为前缀。在静态成员中,this引用类自身。静态类方法非常适合作为实例工厂👇

class Person{
    constructor(age){
    	this.age_ = age;
    }
    
    sayAge(){
    	console.log(this.age_);
    }
    
    static create(){
    	//使用随即年龄创建并返回一个Person实例
    	return new Person(Math.floor(Math.random()*100);
    }
}

4.非函数原型和类成员

可以在外部添加手动添加方法和数据。

5.迭代器与生成器方法

继承

类继承使用的是新语法,但背后依旧使用的是原型链。

1.继承基础

ES6类支持单继承。使用extends关键字,就可以继承人和拥有[[Construct]]和原型的对象。很大程度上,这意味着不仅可以继承一个类,也可以继承普通的构造函数(保持向后兼容):

class Vehicle {}

//继承类
class Bus extends Vehicle {}

let b = new Bus();
console.log(b instanceof Bus);
console.log(b instanceof Vehicle);

function Person() {}

//继承普通构造函数
class Engineer extends Person {}

let e = new Engineer();
console.log(e instanceof Engineer);
console.log(e instanceof Person);

派生类都会通过原型链访问到类和原型上定义的方法。this值回反应调用相应方法的实例或者类。

2.构造函数、HomeObject和super()

派生类方法可以通过super关键字引用他们的原型。这个关键字只能派生类使用,而且仅限于类构造函数、实例方法和静态方法内部。在类构造函数中使用super可以调用父类构造函数。

3.抽象基类

4.继承内置类型

5.类混入

文章内容参考:JavaScript高级程序设计(第四版)

标题样式来自:juejin.cn/post/684490…

哪里写错了就联系我🐧:54269504