ES6类相关

56 阅读3分钟

class

class是一种语法糖,其实就是构造函数及其原型的另一种写法,本质上是函数,换种写法提高可读性和维护性。

语法:

声明:不可提升,必须要new才可以执行

class Person {} // 函数声明
let Person = class{} // 函数表达式
new Person() // 执行

方法私有化

私有属性就是在构造器上通过this绑定的属性,公有属性的方法是原型上的方法

直接在class函数内部声明一个变量,会自动挂载到构造函数上,还是私有属性

class Person{
    a = 1;
}
new Person();

会自动变成

class Person{
    constructor(){
        this.a = 1;
    }
}

一般来说属性都在构造器里私有,方法都是公有的

要想让公有方法私密化(公有属性的私有方法),方案如下:

法1. Symbol

const eat = Symbol();
class Person{
	constructor(name, age){
		this.name = name;
		this.age = age;	
	}
	
	say(){
		console.log(1);
	}

	[eat](){
		console.log('I can eat');
	}
}
console.log(new Person().eat()); //无法访问

法2. 直接在外面定义

class Person{
	constructor(name, age){
		this.name = name;
		this.age = age;	
	}
	
	say(baz){
		children.call(this, baz);
	}
}
function children(baz){
    return this.bar = baz;
}

static 静态属性和方法

静态方法是不会被实例继承的,而是通过类直接调用的

class Person{
    static a(){
        console.log(a);
    };
}
console.log(Person.a);

静态属性

class Person{
    static a = 1;
}

这样定义属性(static a = 1)也可以,但是有兼容性问题,是比较新的做法,一般不会这么做

比较多的做法是:

class Person{}
Person.a = 1;

取值函数和存值函数

对象中定义

var obj = {
    get a(){
        console.log(a);
    },
    set b(val){
        console.log(2);
    }
}
obj.a;

类当中也可

class Person{
    get a(){
        console.log(a);
    }
    set b(val){
        console.log(2);
    }
}
let person = new Person();
person.a;
person.b = 4; //2

get和set不要认为是一种方法,是一种取值和存值的操作,就当属性那样访问就好了

继承extends

ES6当中的继承非常容易,以前要来回倒腾原型链

super用法: 在constructor中,以函数的方式执行

class Parent{
    constructor(name = 'zhangsan'){
        this.name = name;
    }
    static a(){
        console.log(1);
    };
}

//派生类
class Child extends Parent{
    constructor(name = 'lisi', age = '18'){
        //this.age = age; 这里的this的指向是有问题的,super必须在构造器内部,使用this之前要先用super把父级的整个实例继承过来,才可以用this
        super(name); //加工父级构造器,拿到基于父级实例,过了一遍之后返回实例
        this.age = age;
        this.type = 'child';
    }
}
console.log(new Child());
console.log(new Child().a()); //报错
console.log(Parent.a); //1
console.log(new Child().age);

修饰器模式

定义:为对象添加新的功能,而不改变原有的结构和功能

语法:@ + 自定义关键字,修饰和它相邻的下一个方法

@testable
class Person{
	constructor(name, age){
		this.name = name;
		this.age = age;	
	}
	
	@readonly
	say(){
		console.log(1);
	}

	eat(){
		console.log('I can eat');
	}
}
function readonly(target, name, descriptor){
    console.log(target, name, descriptor); // Person、属性名say、say属性描述符
    descriptor.writable = false;
}
function testable(target){
    console.log(target); // Person
}
let person = new Person();
person.say();

target就是当前要修饰的对象:整个Person

通过参数添加一系列功能,实现业务和逻辑相分离。

埋点分析:每做一个数据操作,就有数据处理对应的动作,类似控制台日志。

//埋点代码,记录相应函数执行所对应的结果
let log = (type) => {
    return function(target, name, descriptor){
        let src_method = descriptor.value; //descriptor.value就是对应的函数
        descriptor.value = (...arg) => { //动态的值,不能用src_method替代
            src_method.apply(target, arg);
            console.log(type);
        }
    }
}

class AD{
    //逻辑代码
    @log('show')
    show(){
        console.log('ad is show');   
    }
    
    @log('click')
    click(){
        console.log('ad is click');
    }
}

let ad = new AD();
ad.show();
ad.click();

主体逻辑在一部分,埋点逻辑在另外一部分,复用性更强

设计模式总原则:开放封闭原则(多拓展开放,对修改封闭)