ES6 Class

和 ES5 的对比和基本说明

  1. function Point(x, y) {
  2. this.x = x;
  3. this.y = y;
  4. }
  5. Point.prototype.toString = function () {
  6. return '(' + this.x + ', ' + this.y + ')';
  7. };
  8. const p = new Point(1, 2);
  9. // 使用 class 之后
  10. class Point {
  11. constructor(x, y) {
  12. this.x = x;
  13. this.y = y;
  14. }
  15. toString() {
  16. return '(' + this.x + ', ' + this.y + ')';
  17. }
  18. }
  19. const p = new Point(1, 2);

上面的代码中定义了一个“类” 类名是 Pointconstructor 是它的方法体。所以 p.constructor === Point.prototype.constructor

Class 基本语法


class Point {
    toString() {
        ...
    }
    toValue() {
        ...
    }
    toKeys() {
        ...
    }

    // ES7 中的写法 ES6 不支持
    name = "ccc"
}

var const = new Point(1, 2);

// 等同于

Point.prototype = {
    toString(){},
    toValue(){},
    toKeys(){}
}

上面的 class 里面定义了一个 toString() 方法,在 Point 里面写的方法会直接写在原型上。在 ES6 在 class 里面直接赋值会报错,在 ES7 中不会。

静态方法

在前面加上 static 关键字,该方法不会被实例继承,只能使用。这种就叫静态方法

class Fun {
    // 在前面加上 static 关键字,该方法不会被实例继承,只能使用
    static name (){
        return 'MyFun';
    }
}

Fun.name(); // 'MyFun'

let fun = new Fun();
fun.name();
// TypeError: fun.name is not a function

上面的代码中,name 方法前有 static 关键字,表示 name 是一个静态方法,可以 Fun.name() 调用,而不是在 fun 调用。

继承和 super


class Fun {
    static name (){
        return 'MyFun';
    }
}

class Box extends Fun {

}

Box.name() // 'MyFun'

上面代码中,Fun 有一个静态方法,Box 继承 Fun 之后可以调用这个方法。

可以使用 super,调用父类的静态方法。


class Fun {
    static name (){
        return 'MyFun';
    }
}

class Box extends Fun {
    static name () {
        console.log(super.name() + ', ccc')
    }
}

Box.name() // 'MyFun,ccc'

ES7 Class 的新特性

  • static prop = xxx; 静态属性
  • property = xxx; 私有属性
  • @decortor 装饰器

静态属性和私有属性

我在上面文章说了,在 ES7 中可以直接 static prop = xxx 写静态属性,也可以 myName = 'ccc' 写私有属性


class Fun {
    static name = 'ccc'; // 静态属性
    constructor(){
        this.keyValue = ''
    }
    myName = 'ccc'; // 私有属性
    getCount(){
        console.log('发送请求')
    }
}

var fun = new Fun()

@decortor 装饰器

装饰器的本质还是一种函数

修饰私有属性


class Fun {
    constructor(){
        this.keyValue = ''
    }
    @name
    myName = 'ccc';
}

function name(proto, key, descriptor){
    console.log(proto, key, descriptor)
    // console.log(原型, 属性, descriptor)
    // descriptor 和之前说的 Object.defineproperty 一样是描述符
    // 四个属性
    configurable // 配置
    enumerable  // 枚举
    writable    // 写入
    // 前面三个不做介绍

    initializer // 属性值 
    console.log(descriptor.initializer) // 输出 "ccc"

    // 修改 initializer
    descriptor.initializer = function(){
        return "xxx"
    }
}


var fun = new Fun() // 不 new 修饰器里面的方法都可以执行

console.log(fun.myName) // 输出 "xxx"

修饰原型上的属性


class Fun {
    constructor(){
        this.keyValue = ''
    }
    @myCount
    getCount(){
        console.log('发送请求')
    }

    @myBox
    box=()=>{
        console.log('发送请求')
    }
}

function myCount(proto, key, descriptor) {
    console.log(proto, key, descriptor)
    // console.log(原型, 属性, descriptor)
    // descriptor 和之前说的 Object.defineproperty 一样是描述符
    // 四个属性
    configurable // 配置
    enumerable  // 枚举
    writable    // 写入
    // 前面三个不做介绍

    value // 方法体
    console.log(descriptor.value) // 就是 getCount() 这个方法体

    // 修改 value
    descriptor.value = function(){
        console.log("666");
        console.log(this); // 输出的是 fun
    }
}

function box (){
    // 箭头函数的时候 
    console.log(proto, key, descriptor)
    // console.log(原型, 属性, descriptor)
    // descriptor 和之前说的 Object.defineproperty 一样是描述符
    // 四个属性
    configurable // 配置
    enumerable  // 枚举
    writable    // 写入
    // 前面三个不做介绍
    // 还是 initializer
    initializer // 属性值 

}

var fun = new Fun() 

console.log(fun.getCount()) // 输出 666

上面的代码中在装饰原型上面的方法的时候 initializer 会变成 value,会指向被装饰的方法体,可以通过去 descriptor.value=fun(){} 的方式去修改。

装饰类


@boxs
class box {
    constructor (){
        console.log("我是constructor")
    }
}

function boxs (target) {
    target.name = "ccc" // 可以这样子直接加属性
}