类字段和方法

字段

类字段直接在类的正文中声明,而不是显式地作为 this 值的属性添加。但是,结果是相同的:在类的实例上定义的属性。

class MyClass {
    myField;
}

const myClassInstance = new MyClass();

myClassInstance;
> MyClass { myField: undefined }

您可以初始化具有值的字段。这通常是一个默认值,类中的逻辑可以覆盖该值

class MyClass {
    myResult = false;
    set setValue( myValue ) {
        this.myResult = myValue;
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> Object { myResult: false }

myClassInstance.setValue = true;

myClassInstance;\
> Object { myResult: true }

类字段在功能上与使用 this 附加到类的属性相同。这意味着可以像任何其他属性一样从类外部访问和修改它们。

class MyClass {
    myField = true;
}

const myClassInstance = new MyClass();

myClassInstance.myField;
> true

myClassInstance.myField = false;

myClassInstance.myField;
> false;

字段为类的某些更高级功能提供了基础。

私有字段和方法

私有字段和方法在类外部不可访问。私有属性与类的实例关联,这意味着每个实例都包含其自己的一组私有字段和方法,如类上定义的那样。

要使属性成为私有属性,请在声明标识符时在标识符的开头添加 #

class MyClass {
    #myPrivateField = true;
    #myPrivateMethod() {}
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass { #myPrivateField: true }
    #myPrivateField: true
    <prototype>: Object {  }
        constructor: class MyClass {}
        <prototype>: Object {  }

必须在包含类的正文中声明私有字段。您可以在以后将其值更改为 this 的属性,但不能使用 this 创建该字段。

私有字段无法从脚本的其他位置访问。这可以防止数据属性在提供的 getter 和 setter 方法之外被更改以与它们包含的值进行交互,并且可以防止直接访问仅供类本身内部使用的方法。

class MyClass {
    #myResult = false;
    set setValue( myValue ) {
        this.#myResult = myValue;
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass { #myResult: false }

myClassInstance.#myResult = true;
> Uncaught SyntaxError: reference to undeclared private field or method #myResult

myClassInstance.setValue = true;

myClassInstance;\
> MyClass { #myResult: true }

但是,请记住,浏览器开发人员控制台通常在允许访问私有字段以进行调试方面 非常宽松,尽管不一致

class MyClass {
    #myPrivateField = true;
    #myPrivateMethod() {
        console.log( "This is inside a private method." );
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass {#myPrivateField: true}

myClassInstance.#myPrivateField;
> true

myClassInstance.#myPrivateMethod();
> "This is inside a private method."
class MyClass {
    #myPrivateField = true;
    #myPrivateMethod() {
        console.log( "This is inside a private method." );
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass {#myPrivateField: true}

myClassInstance.#myPrivateField;
> Uncaught SyntaxError: reference to undeclared private field or method #myPrivateField

myClassInstance.#myPrivateMethod();
> Uncaught SyntaxError: reference to undeclared private field or method #myPrivateMethod

私有字段的范围严格限制在包含它们的类的正文中,这意味着即使子类也无法访问与父类关联的私有字段

class MyClass {
    #myPrivateField = true;
}
class ChildClass extends MyClass {
    childMethod() {
        console.log( this.#myPrivateField );
    }
}
> Uncaught SyntaxError: reference to undeclared private field or method #myPrivateField

静态字段和方法

静态字段和方法是类本身的成员,而不是该类的实例的成员。因此,静态字段为数据提供了一个中心点,该数据对于类的每个实例不是唯一的,但这些实例可能需要引用——例如,共享配置信息。静态方法通常是用于处理类实例的实用程序函数,例如比较实例或根据它们包含的字段对实例进行排序。

要在类的正文中定义静态字段和方法,请使用 static 关键字

class MyClass {
    static myStaticField;
    static myStaticMethod() {}
}
const myClassInstance = new MyClass();

您还可以使用点表示法创建静态方法

class MyClass {
    constructor() {}
}
MyClass.myStaticMethod = function() {}

您无法从其类的实例访问静态属性,但它们在类构造函数上可用

class MyClass {
    static myStaticField = true;
    static myStaticMethod() {
        console.log( "A static method." );
    }
}
const myClassInstance = new MyClass();

myClassInstance.myStaticField;
> undefined

myClassInstance.myStaticMethod();
> Uncaught TypeError: myClassInstance.myStaticMethod is not a function

MyClass.myStaticField;
> true

MyClass.myStaticMethod();
> "A static method."

它们在技术上不是必需的,但使用静态方法是创建实用程序以处理类实例的最佳实践。这方面的示例可能包括专用于对类实例进行排序的静态方法,或包含创建类实例所需的任何设置然后返回类实例的静态工厂方法

class User {
    constructor( name, email ) {
        this.name = name;
        this.email = email;
    }
    static fromObject( myObject ) {
        return new User( myObject.name, myObject.email ?? "Omitted" );
    }
}
const userObject = {
    "name" : "My Name",
    "email" : "my@email.address"
};
const secondUserObject = {
    "name" : "My Name"
};

const firstUser = User.fromObject( userObject );
const secondUser = User.fromObject( secondUserObject );

firstUser;
> Object { name: "My Name", email: "my@email.address" }

secondUser;
> Object { name: "My Name", email: "Omitted" }

检查您的理解

以下哪种类型的字段只能从类内部访问?

私有字段
类字段
静态字段