传统的构造函数的问题

1. 属性和原型方法定义分离,降低了可读性
2. 原型成员可以被枚举
3. 默认情况下,构造函数仍然可以被当作普通函数使用

类的特点

1. 类声明不会被提升,与 let 和 const 一样,存在暂时性死区

2. 类中的所有代码均在严格模式下执行

3. 类的所有方法都是不可枚举的

4. 类的所有方法都无法被当作构造函数使用

5. 类的构造器必须使用 new 来调用

示例

普通构造函数

  1. function Hexo(name, age, sex) {
  2. this.name = name;
  3. this.age = age;
  4. this.sex = sex;
  5. }
  6. Hexo.prototype.print = function () {
  7. console.log(`【名字】:${this.name}`);
  8. console.log(`【年龄】:${this.age}`);
  9. console.log(`【性别】:${this.sex}`);
  10. }
  11. const hexo = new Hexo('张三', '10', '男')
  12. console.log(hexo)
  13. for (const prop in hexo) {
  14. console.log(prop)
  15. }

控制台打印结果
image.png

类的示例

  1. class Hexo {
  2. constructor(name, age, sex) {
  3. this.name = name;
  4. this.age = age;
  5. this.sex = sex;
  6. }
  7. print() {
  8. console.log(`【名字】:${this.name}`);
  9. console.log(`【年龄】:${this.age}`);
  10. console.log(`【性别】:${this.sex}`);
  11. }
  12. }
  13. const hexo = new Hexo('张三', '10', '男')
  14. console.log(hexo)
  15. for (const prop in hexo) {
  16. console.log(prop)
  17. }

控制台打印结果
image.png

类的其他书写方式

可计算的成员名

  1. const hexoName = 'hexoName';
  2. const hexoAge = 'hexoAge';
  3. const hexoSex = 'hexoSex'
  4. class Hexo{
  5. constructor(name,age,sex){
  6. this.name = name;
  7. this.age = age;
  8. this.sex = sex;
  9. }
  10. [hexoName](){
  11. console.log(this.name)
  12. }
  13. [hexoAge](){
  14. console.log(this.age)
  15. }
  16. [hexoSex](){
  17. console.log(this.sex)
  18. }
  19. }
  20. const hexo = new Hexo('张三','10','男')
  21. hexo[hexoName]();

访问器属性

当其属性值有其限制时就可以使用访问器属性,es5中Object.defineProperty 可定义某个对象成员属性的读取和设置
使用getter和setter控制的属性,不在原型上
getter 无参数
setter 单参数

  1. class Animal {
  2. constructor(type, name, age, sex) {
  3. this.type = type;
  4. this.name = name;
  5. this.age = age;
  6. this.sex = sex;
  7. }
  8. //创建一个age属性,并给它加上getter,读取该属性时,会运行该函数
  9. get age() {
  10. return this._age + "岁";
  11. }
  12. //创建一个age属性,并给它加上setter,给该属性赋值时,会运行该函数
  13. set age(age) {
  14. if (typeof age !== "number") {
  15. throw new TypeError("age property must be a number");
  16. }
  17. if (age < 0) {
  18. age = 0;
  19. }
  20. else if (age > 1000) {
  21. age = 1000;
  22. }
  23. this._age = age; // _age 下划线为系统保留属性,去掉会让程序误认为 this.age = age 这样不就是赋值吗,给age赋值不就会调用set age 这个方法吗
  24. // 这样不就递归,最后会导致栈溢出
  25. }
  26. }
  27. var a = new Animal("狗", "旺财", 3, "男");

静态成员 / 字段初始化器(ES7)

其区别
使用static的字段初始化,添加的是静态成员
没有使用static的字段初始化器,添加的成员位于对象上
箭头函数在字段初始化器位置上,指向当前对象

静态成员

构造函数本身的成员
何为静态成员看笔记类/包装类/静态属性与成员属性,说白啦就是静态成员只能自身调用,实例化后的不能调用

  1. class hexo {
  2. // es6 的写法
  3. static type = '人';
  4. static func (){
  5. console.log('也可使定义静态方法')
  6. }
  7. constructor(name, age, sex){
  8. this.name = name;
  9. this.age = age;
  10. this.sex = sex;
  11. }
  12. }
  13. // 以前构造函数的写法
  14. // hexo.type = 'ren';
  15. const h = new hexo('张三','10','男')

image.png
如上图 静态成员在其自身上

字段初始化器(ES7)

  1. class hexo {
  2. // es7 使用字段初始化器的写法 与小面为未使用的一致,只是写法不一样
  3. sex='男'
  4. conSex(){
  5. console.log(this.sex)
  6. }
  7. constructor(name, age) {
  8. this.name = name;
  9. this.age = age;
  10. // es6的写法,未使用字段初始化器的写法
  11. this.sex = '男';
  12. }
  13. }
  14. const h = new hexo('张三','10');

image.png
从上图看出 使用字段初始化器添加的成员在其对象上。

类的表达式

匿名类

  1. const A = class { //匿名类,类表达式
  2. a = 1;
  3. b = 2;
  4. }
  5. const a = new A();
  6. console.log(a)