JS 类总结
创始人
2024-02-02 14:58:53
0

class 关键字是 ES6 新增的。类(class)是ECMAScript 中新的基础性语法糖,本质上还是一个函数,但实际上它使用的仍然是原型和构造函数的概念。并且类受块级作用域限制。

class Person { }
console.log(Person);// class Person { }

定义类

类定义中的代码默认都在严格模式下执行。类包含如下可选内容:

  • 构造函数方法
  • 实例方法
  • 获取函数
  • 设置函数
  • 静态类方法。

空的类定义照样有效。

  • 类声明
    类定义没有像函数那样的声明提升。
class Person {} 
  • 类表达式
    类表达式不能在它们被求值前使用。
const Animal = class {}; 

类的组成

构造函数

在使用 new 操作符创建类的新实例时,会调用 constructor 方法,主要作用是初始化数据。不是必需的,不定义构造函数相当于将构造函数定义为空函数。

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

  1. 在内存中创建一个新对象。
  2. 这个新对象内部的 [[Prototype]] 指针被赋值为构造函数的 prototype 属性。
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。
  4. 执行构造函数内部的代码(给新对象添加属性)。
  5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。
class Animal { }
class Person {constructor(name) {this.name = name;}
}
let animal = new Animal();
let person = new Person('孤城浪人');
console.log(animal); //Animal {}
console.log(person); //Person {name: '孤城浪人'}

默认情况下,constructor 会在执行之后返回当前实例对象。如果 constructor 显示的 return 了一个对象,那么这个对象不会通过 instanceof 操作符检测出跟类有关联,因为这个对象的原型指针并没有被修改。

class Person {constructor(name) {this.foo = name;if (name) {return {name: 'XXXXX'};}}
}
let p1 = new Person(),p2 = new Person('孤城浪人');
console.log(p1); // Person {foo: undefined}
console.log(p1 instanceof Person); // true 
console.log(p2); // {name: 'XXXXX'}
console.log(p2 instanceof Person); // false

我们可以调用实例的 constructor 方法,因为他就是普通函数,只是必须使用 new 关键字调用罢了。

class Person {constructor(name) {this.foo = name;}
}
let p1 = new Person('孤城浪人'),p2 = new p1.constructor('XXXXX');
console.log(p1); // Person {foo: undefined}
console.log(p2); // Person {name: 'XXXXX'}

类可以立即调用

const person = new class Person {constructor(name) {this.name = name;}
}('孤城浪人')
console.log(person);// Person {name: '孤城浪人'}

成员

每次通过 new 调用类标识符时,都会执行类构造函数,这也就意味着在 constructor 中定义的成员每个实例都是一份新的,不会共享。但是不是在 constructor 中定义的成员(不能是原始值或对象)是定义在类的原型上,所有类的实例共享。

const person = class Person {constructor(name) {// 不共享this.name = name;}// 定义在类原型上共享sayName() {console.log(this.name);}
}

类定义也支持获取和设置访问器,方法名支持字符串、符号或计算的值。

class Person {set name(newName) {this.name_ = newName;}get name() {return this.name_;}['sa' + 'y']() {console.log('xxxx');}
}
new Person().say();

静态方法

类可以定义静态方法。它的调用不依赖于实例,静态方法的方法名不能重复

class Person {static sayHellow() {console.log('Hellow');}static say() {console.log('xxxx');}
}
Person.say();//Hellow
Person.sayHellow();//xxxx

迭代

类支持在原型和类本身定义生成器方法,因此可以添加一个默认的迭代器,把类实例变成可迭代对象。

class Person {constructor() {this.names = ['孤城浪人', 'xxxx']}// [Symbol.iterator]() {//   return this.names.entries();// }*[Symbol.iterator]() {yield* this.names.entries();}
}
const person = new Person();
for (let item of person) {console.log(item);
}
// [0, '孤城浪人']
// [1, 'xxxx']

继承

这是类最优秀的特性,原生支持继承,但是本质上还是利用了原型链。使用 extends 关键字,就可以继承任何拥有[[Construct]]和原型的对象,前面说过类就是一个语法糖,他本质上是一个函数,所以 extends 不仅可以继承一个类,也可以继承普通的构造函数。并且 this 永远指向当前实例。

function Person() { };
class Father extends Person {say() {console.log(this);}
}
class Son extends Father { }
const son = new Son();
console.log(son instanceof Father);//true
console.log(son instanceof Person);//true
son.say();//Son{}

这个例子可以看到 Father 继承 Person,Son 继承 Father,所以最后 Son 的实例的原型链中有 Father
和 Person 的原对象,因此 instanceof 返回 true。

super

如果子类需要调用父类的构造函数 constructor 初始化数据,那么只能在子类的构造函数中使用 super 关键字,此外在实例方法和静态方法内部也可以使用 super 关键字。(ES6 给类构造函数和静态方法添加了内部特性 [[HomeObject]] 指向定义该方法的对象。 super 始终会定义为 [[HomeObject]] 的原型)

注意:子类若定义了 constructor 则一定要调用 super,并且不要在调用 super 之前引用 this,否则会抛出 ReferenceError,

class Father {constructor(name) {this.name = name;}say() {console.log(this);}
}
class Son extends Father {constructor() {super('孤城浪人');}sayName() {console.log('sayName')super.say();}
}
const son = new Son();
son.sayName();
// sayName
// Son { name: '孤城浪人' }

如果子类没有构造函数,在实例化子类时会自动调用 super(),而且会把所有传给子类的参数作为 super 的参数传入。

class Father {constructor(name) {this.name = name;}say() {console.log(this);}
}
class Son extends Father {}
const son = new Son('孤城浪人');
son.say();
//Son { name: '孤城浪人' }

抽象基类

抽象基类就是可供其他类继承,但本身不会被实例化的类。可以在构造函数中使用 new.target 属性阻止抽象基类实例化,也可以在其中强制子类要定义某个方法。

class Father {constructor(name) {if (new.target == Father) {throw new Error('不能实例化');}if (!this.say) {throw new Error('缺少say方法');}}
}
class Son extends Father {constructor(name) {super();this.name = name;}say() {console.log(this.name);}
}
const son = new Son('孤城浪人');
son.say();//孤城浪人
new Father()

在这里插入图片描述

我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...