class

178 阅读2分钟

1.简介:ES6 Class(类)是 ES5构造函数的语法糖

// ES5
function Point(x, y) {
    this.x = x;
    this.y = y;
}

Point.prototype.toString = function() {
    return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);


// ES6

class Point {
    constructor(x, y) {
            // constructor()方法默认返回实例对象(即this),完全可以指定返回另外一个对象。
            // x和y都是实例对象point自身的属性(因为定义在this对象上),
            this.x = x;
            this.y = y;
            // return Object.create(null);
        }
        // toString()是原型对象的属性(因为定义在Point类上)
    toString() {
        return `(${this.x},${this.y})`
    }

}
const point = new Point(1, 2)

point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true

2静态方法(只能构造函数本身调用,实例无法调用)

 class Foo {
    static bar() {
        // 2.1 如果静态方法包含this关键字,这个this指的是类,而不是实例。
        this.baz();
    }
    static baz() {
        console.log('hello');
    }
    baz() {
        console.log('world');
    }
}

Foo.bar() // hello()

var foo = new Foo();
// foo.bar() //// TypeError: foo.bar is not a function

// 2.2 父类的静态方法,可以被子类继承。
class Bar extends Foo {
    static bar() {
        //2.3 静态方法也是可以从super对象上调用的。
        return super.bar() + ', too';
    }
}
Bar.bar() //fix 没有打印too

3实例属性的新写法

实例属性除了定义在constructor()方法里面的this上面,也可以定义在类的最顶层。

  class IncreasingCounter {
        constructor() {
            this._count = 0;
        }
        get value() {
            console.log('Getting the current value!');
            return this._count;
        }
        increment() {
            this._count++;
        }
    }
 class IncreasingCounter {
    // 这时,不需要在实例属性前面加上this。
    _count = 0;
    get value() {
        console.log('Getting the current value!');
        return this._count;
    }
    increment() {
        this._count++;
    }
}

4 静态属性

静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。

// 老写法
class Foo {
    // ...
}
Foo.prop = 1;

// 新写法
class Foo {
    static prop = 1;
}

5 私有方法和私有属性

私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问。这是常见需求,有利于代码的封装,但 ES6 不提供,只能通过变通方法模拟实现。

私有属性的提案 : 目前,有一个提案,为class加了私有属性。方法是在属性名之前,使用#表示。

注意点: (1)严格模式:类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式 (2)不存在提升 (3)name 属性 (4)Generator 方法 (5)this 的指向

类的方法内部如果含有this,它默认指向类的实例.但是,必须非常小心,一旦单独使用该方法,很可能报错。

 class Logger {
    printName(name = 'there') {
        this.print(`Hello ${name}`);
    }

    print(text) {
        console.log(text);
    }
}

const logger = new Logger();
const {
    printName
} = logger;
printName(); // TypeError: Cannot read property 'print' of undefined

一个比较简单的解决方法是,在构造方法中绑定this,这样就不会找不到print方法了。

  class Logger {
    constructor() {
        this.printName = this.printName.bind(this);
    }

    // ...
}

另一种解决方法是使用箭头函数。

    class Obj {
        constructor() {
            this.getThis = () => this;
        }
    }

    const myObj = new Obj();
    myObj.getThis() === myObj // true

还有一种解决方法是使用Proxy,获取方法的时候,自动绑定this。