关于javascript es6 class中static方法的使用场景

我们知道在class中定义的static方法,在使用时可以直接调用,不用实例化,我的疑惑是

  1. 在定义类的方法的时候,什么方法适宜定义成static,什么方法不用?
  2. 我可不可以把类中的方法都定义为static,这样做有什么弊端没有?

还请各位大神详细介绍下class的适用场景以及static的适用场景,不胜感激!

阅读 15.2k
2 个回答

在OOP中,带方法的类(即非数据类),一般有两个作用

  • 封装方法和属性(通常意义的 OOP 类)
  • 封装临时变量(和来处理复杂事务的类)

不管哪个作用,方法通常都是会操作成员变量的,这种情况下,肯定只能写实例方法(因为要操作成员)

除此之外,不需要访问类属性的方法都可以写成静态的,这类方法一般都是 Helper 方法,即对输入进行处理再得到一个输出,与对象的成员无关。这类方法也可以直接写为公共函数(非方法函数)。不过在 C#、Java、TypeScript 等有权限限制的语言中,静态方法可以访问对象的私有成员,比如 Foo 类的 Foo.bla(f: Foo) 静态方法内部可以直接访问 f.somePrivateMethod(),当然目前 JavaScript 中不存在这种情况,以后引入私有成员之后会不会存在这种情况也还要观望

顺便说一下,多数静态类型语言中成员方法都是可以直接调用同一个类的静态方法的,但 JavaScript 由于实现机制不能,做不到。

回看有惊喜,2020-02-27 更新

JavaScript 的私有字段提议已经到了 stage-3 (实验) 阶段,TypeScript 3.8 和 Chrome 7.4 已经支持私有字段,那么前面提到的疑惑其实是可以实验来验证的

实验环境:

用 Edge 而没用 Chrome 主要是因为墙的问题,以及,懒得装了,反正新版 Edge 也是 Chrominum 核心

实验代码,TypeScript

class MyClass {
    static create(name: string, age: number = 10) {
        var obj = new MyClass();
        obj.#name = name;
        obj.#age = age;
    }

    #name: string;
    #age: number;

    constructor() {
        this.#name = "Default Name";
        this.#age = 0;
    }

    toString(): string {
        return `${this.#name}: ${this.#age}`;
    }
}

const inst = MyClass.create("James", 10);
// inst.#name = "Hello";

console.log(inst.toString());

结论

  • 静态方法(static create()) 中可以访问对象的私有成员 (#name#age
  • 外部不能访问对象的私有成员(inst.#name = "Hello" 会报错)

泻药,静态方法的食用方式你也知道了,那么问题1也不言而喻,不属于实例的方法都应该是静态的,比如 Array.isArray, Array.from ,都是跟实例无关的,一般就是一些 helper 方法。至于问题2,这么做是不行的,static 之后实例中就不能调用这些方法了。

推荐问题
宣传栏