es6新增类详解

为什么要用类

在解释这个问题之前,我们先来看看传统的构造函数的问题

  1. 属性和原型方法定义分离,降低了可读性
  2. 原型成员可以被枚举(for in循环能拿到原型上的属性和方法)
  3. 默认情况下,构造函数可以被当做普通函数使用

类的特点

  1. 类声明不会被提升,存在暂时性死区
  2. 类中的所有代码都在严格模式下执行
  3. 类的所有方法都是不可枚举的
  4. 类的所有方法不能被当做构造函数使用
  5. 类的构造必须使用new来调用

例子

1.传统的构造函数

function Animal(type, name, age){
    this.type = type;
    this.name = name;
    this.age = age;
}
Animal.prototype.print = function(){
    console.log(`种类:${this.type}`);
    console.log(`名字:${this.name}`);
    console.log(`年龄:${this.age}`);
}
const dog = new Animal("狗", "旺财", 3);
dog.print();
for (const prop in dog) {
    console.log(prop);
}

在这里插入图片描述
2.es6类的写法

class Animal {
  constructor(type, name, age) {
    this.type = type;
    this.name = name;
    this.age = age;
  }
  print() {
    console.log(`种类:${this.type}`);
    console.log(`名字:${this.name}`);
    console.log(`年龄:${this.age}`);
  }
}
const dog = new Animal("狗", "旺财", 3);
dog.print();
for (const prop in dog) {
    console.log(prop);
}

在这里插入图片描述

类的其他书写形式

  1. 可计算的成员名
const printName = "print";

class Animal{
    constructor(type, name, age, sex){
        this.type = type;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    [printName](){
        console.log(`[种类]:${this.type}`);
        console.log(`[名字]:${this.name}`);
        console.log(`[年龄]:${this.age}`);
        console.log(`[性别]:${this.sex}`);
    }
}

const a = new Animal('狗', '旺财', 3, '男');
a[printName]();

在这里插入图片描述

  1. getter和setter,使用getter和setter控制的属性,不在原型上
const printName = "print";
class Animal {
    constructor(type, name, age, sex) {
        this.type = type;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    //创建一个age属性,并给它加上getter,读取该属性时,会运行该函数
    get age() {
        return this._age + "岁";
    }
    //创建一个age属性,并给它加上setter,给该属性赋值时,会运行该函数
    set age(age) {
        this._age = age;
    }
    [printName]() {
        console.log(`【种类】:${this.type}`);
        console.log(`【名字】:${this.name}`);
        console.log(`【年龄】:${this.age}`);
        console.log(`【性别】:${this.sex}`);
    }
}
var dog = new Animal("狗", "旺财", 3, "公");
//如果get和set使用类的age就会无限调用方法,所以必须返回一个跟age名不一样的变量名

在这里插入图片描述

  1. 静态成员。使用static关键字定义的成员即静态成员。只能自己使用
class Chess {
    constructor(name) {
        this.name = name;
    }
    static width = 50;
    static height = 50;
}
var a = new Chess();
console.log(Chess.width)
console.log(Chess.height)
console.log(a.width);
console.log(a.height);

在这里插入图片描述

  1. 类表达式
const A = class {
    a = 1;
    b = 2;
}
const a = new A();
console.log(a)

在这里插入图片描述

类的继承

如果B继承自A,则A派生B,B是A的子类,A是B的父类,B自动拥有A中的所有实例成员

关键字

extends:继承,用于类的定义
super:
1.如果直接当做函数调用,表示父类的构造函数
2.如果当做对象调用,则表示父类的原型

注意

如果子类定义了constructor,则必须在constructor的第一行手动调用父类的构造函数,如果子类不写constructor,则会有默认的构造器,参数和父类一致,并自动调用父类构造器

例子

这是一个抽象类

class Animal {
    constructor(type, name, age, sex) {
        if (new.target === Animal) {
            throw new TypeError("你不能直接创建Animal的对象,应该通过子类创建")
        }
        this.type = type;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    print() {
        console.log(`【种类】:${this.type}`);
        console.log(`【名字】:${this.name}`);
        console.log(`【年龄】:${this.age}`);
        console.log(`【性别】:${this.sex}`);
    }
    say() {
        throw new Error("动物怎么叫的?");
    }
}
class Dog extends Animal {
    constructor(name, age, sex) {
        super("犬类", name, age, sex);
        // 子类特有的属性
        this.loves = "吃骨头";
    }
    print() {
        //调用父类的print
        super.print();
        //自己特有的代码
        console.log(`【爱好】:${this.loves}`);
    }
    //同名方法,会覆盖父类
    say() {
        console.log("汪汪!");
    }
}
const a = new Dog("旺财", 3, "公")
a.print();
a.say();

es6新增类详解_第1张图片

你可能感兴趣的:(es6)