For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/stage/1/proposal-private-declarations.md.
  • 简体中文
  • Private declarations S1

    中文标题:私有声明

    提案概览
    提案速览

    该提案添加私有声明,允许类词法作用域之外的可信代码访问私有状态。它还允许将私有状态添加到普通对象上。语法使用 private #name; 声明,随后可以按通常的 #name 语法访问私有字段。可能的后续提案可以允许将私有声明共享给友好模块。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    私有声明

    一项添加私有声明的提案,允许类词法作用域_之外_的可信代码访问私有状态。

    private #hello;
    class Example {
      #hello = 'world!';
    
      hello() {
        return this.#hello;
      }
    }
    
    const ex = new Example();
    console.log(ex.hello()); // => 'world!'
    console.log(ex.#hello); // => 'world!'

    这还允许我们把私有状态带到普通对象上!

    private #hello;
    function Example() {
      return {
        #hello: 'world',
    
        hello() {
          return this.#hello;
        }
      }
    }
    
    const ex = Example();
    console.log(ex.hello()); // => 'world!'
    console.log(ex.#hello); // => 'world!'

    可能的后续提案 可以允许将私有声明共享给友好模块。

    负责人

    状态

    当前 阶段: 1

    指导用例

    “受保护”状态

    受保护状态在实现类层次结构时是一种有价值的可见性状态。例如,可以使用钩子模式来允许子类覆盖代码:

    // https://github.com/Polymer/lit-html/blob/1a51eb54/src/lib/parts.ts
    
    private #createPart;
    
    class AttributeCommitter {
      //...
    
      #createPart() {
        return new AttributePart(this);
      }
    }
    
    class PropertyCommitter extends AttributeCommitter {
      #createPart() {
        return new PropertyPart(this);
      }
    }

    在这里,AttributeCommitter 显式允许可信的(写在同一个源文件中的)子类覆盖 #createPart 方法的行为。默认情况下,返回普通的 AttributePart。但 PropertyCommitter 只处理属性,并且会返回 PropertyPart。所有其他代码都可以通过 AttributeCommitter 上正常的公开可见字段/方法被继承。

    注意,这并不会赋予文件外代码覆盖 #createPart 方法的特权,因为 #createPart 私有声明只在其声明的作用域中可见。

    友元类/函数

    关于 C++ 中的先例,请参见 https://en.wikipedia.org/wiki/Friend_function。

    AMP 项目有一种特定的分阶段 lint 模式,它与守卫受限代码访问的友元函数配合得很好。首先,静态使用的函数比对象作用域的方法调用更容易进行 lint,因为我们不需要知道对象的类型。因此,判断这是受限调用还是只是使用相同方法名的非受限调用要容易得多。例如,更容易分辨静态导出 registerExtendedTemplate 是受限的,而 obj.registerExtendedTemplate 不是。

    // https://github.com/ampproject/amphtml/blob/18baa9da/src/service/template-impl.js
    
    private #registerTemplate;
    
    // Exported so that it may be intalled on the global and shared
    // across split bundles.
    export class Templates {
      #registerTemplate() {
        //...
      }
    }
    
    // The code privileged to register templates with the shared class
    // instance. Importing and using is statically analyzable, and must pass
    // a linter.
    export function registerExtendedTemplate() {
      const templatesService = getService('templates');
      return templatesService.#registerTemplate(...arguments);
    }

    非类对象工厂

    并非所有代码都想要 class。有时在这种情况下你仍然想要私有字段。

    private #hash;
    
    export function factory(value) {
      return Object.freeze({
        value,
        #hash: someFunction(value),
      });
    }
    
    export function isProducedByMyFactory(value) {
      return #hash in value;
    }
    
    export function equals(a, b) {
      if (a.#hash !== b.#hash) return false;
      return expensiveCompare(a.value, b.value);
    }