聊聊es6之class

类:构造函数的语法糖

传统的构造函数的问题

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

类的写法

在es6的class中一个类的静态方法,私有属性,原型方法均写在了一起,解决了传统构造函数的属性原型分离的问题

class Plane {
    // 静态属性,相当于Plane.alive
    static alive() {
        return true
    }
    constructor(name) { // 这里是参数
        // 私有属性
        this.name = name || '普通飞机';
        this.blood = 100;
    }
    // 原型方法 forin不可枚举此方法
    fly() {
        console.log('fly')
    }
}

类的特点

  • 类声明不会被提升,与 let 和 const 一样,存在暂时性死区
console.log(Plane);
class Plane {
    constructor(type) {
        this.type = type
    }
}
// Uncaught ReferenceError: Cannot access 'Plane' before initialization
  • 类中的所有代码均在严格模式下执行
class Plane {
    constructor(type) {
        this.type = type;
        a = 1
    }
}
new Plane()
// Uncaught ReferenceError: a is not defined
  • 类的所有原型方法都是不可枚举的(私有方法可枚举)
class Plane {
    constructor(type) {
        this.type = type; // 私有属性可枚举
        this.fn = () => {}; // 私有方法可枚举
    }
    fly() {console.log('fly')} // 原型方法不可枚举
}
let p = new Plane();
for (const key in p) {
    console.log(key) // type fn
}
  • 类的所有方法都无法被当作构造函数使用(包括静态方法)
class Plane {
    static fn () { // 静态方法不可new
        this.name = 'a'
    }
    constructor(type) {
        this.type = type;
    }
    fly() {console.log('fly')} // 原型方法不可new
}
let p = new Plane();
new Plane.fn(); // Uncaught TypeError: Plane.fn is not a constructor
new p.fly(); // Uncaught TypeError: p.fly is not a constructor
  • 类的构造器必须使用 new 来调用
class Plane {
    constructor(type) {
        this.type = type; 
    }
}
Plane(); // Uncaught TypeError: Class constructor Plane cannot be invoked without 'new'

类的其他书写方式

  • 可计算属性名
let flyName = 'fly'
class Plane {
    constructor(type) {
        this.type = type; 
    }
    [flyName]() {console.log('fly')} // 计算属性名
}
let p = new Plane(); 
p[flyName]()
  • getter和setter
// 假设飞机寿命只能为0-10年
class Plane {
    constructor(type, age) {
        this.type = type;
        this.age = age
    }
    set age(age) {
        if(age < 0) {
            this._age = 0;
        } else if (age > 10) {
            this._age = 10
        } else {
            this._age = age
        }
    }
    get age() {
        return this._age + '岁'
    }
}
let p = new Plane('plane', 2); 
console.log(p.age) // 2岁
  • 静态成员
class Plane {
    static canFly = true;
    constructor(type, age) {
        this.type = type;
    }
}
console.log(Plane.canFly); // true
  • 字段初始化器
class Plane {
    constructor(type) {
        this.type = type;
    }
    name = '飞机'; // name属性是私有属性
    // 这种写法会将print变为私有方法
    // 由于使用了箭头函数,箭头函数没有this,所以this永远为实例对象
    print = () => {
        console.log(this.type)
    }
}
let p = new Plane('普通飞机');
p.print(); // 普通飞机
let print = p.print; // 即使改变执行环境,也会输出p的type
print(); // 普通飞机
  • 类表达式
let a = class { // 等同于 class a {...}
    constructor() {
        this.a = 1;
        this.b = 2;
    }
}
console.log(new a())

继承

继承有两个新增关键字extends和super
extends用于继承
super两个用法
在constructor里面要先调用super(向父类传入所需参数)
在方法里面使用super,super代表父类的原型
用法如下

class Animal {
    constructor(type, name, age, sex) {
        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}`);
    }
}
class Dog extends Animal {
    constructor(name, age, sex) {
        super('犬类', name, age, sex); // 继承的子类在constructor里面先调super方法,传入父类所需参数
        this.like = '吃骨头'; // 然后添加子类的特有属性(不能写在super前面)
    }
    print() { // 覆盖父类方法
        super.print(); // 调用父类方法使用super
        console.log(`【爱好】:${this.like}`);
    }
}
const a = new Dog("旺财", 3, "男");
a.print()

冷知识
一般情况下,父类是不可以直接new的,创建实例对象是通过子类构造函数来创建,所以可以给父类构造函数做一个处理

class Animal {
    constructor(type, name, age, sex) {
        if (new.target == Animal) { // 可以通过new.target获得创建实例的构造函数
            throw('不能直接通过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}`);
    }
}
class Dog extends Animal {
    constructor(name, age, sex) {
        super('犬类', name, age, sex); // 继承的子类在constructor里面先调super方法,传入父类所需参数
        this.like = '吃骨头'; // 添加子类的特有属性
    }
    print() { // 覆盖父类方法
        super.print(); // 调用父类方法使用super
        console.log(`【爱好】:${this.like}`);
    }
}
发布了7 篇原创文章 · 获赞 38 · 访问量 435

猜你喜欢

转载自blog.csdn.net/qq_45516476/article/details/104343993
今日推荐