Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A private getter in JavaScript defines the getter function of an accessor property that is strictly encapsulated within the lexical scope of its defining class. Denoted by the # (hash) prefix, it enforces strict data hiding at the language level via the ECMAScript private class features specification. Unlike TypeScript’s private keyword, which is stripped during compilation, JavaScript private getters are enforced at runtime by the JavaScript engine.

Syntax and Implementation

A private getter is defined using the get keyword followed by a private identifier. In JavaScript’s lexical grammar, get acts as a contextual keyword, while the # and its subsequent characters form a single, distinct PrivateIdentifier token. Because the parser recognizes get and #identifier as two separate tokens that do not require whitespace separation, omitting the space (e.g., get#identifier()) is perfectly valid syntax. Private getters can be defined for both class instances and the class constructor itself (static). They are invoked without parentheses, identical to standard property access.
class Configuration {
  // Instance private getter (whitespace is optional)
  get #instanceConfig() {
    return 'instance-level data';
  }

  // Static private getter
  static get#globalConfig() {
    return 'class-level data';
  }

  readConfig() {
    // Accessed internally via 'this.#identifier'
    return this.#instanceConfig; 
  }

  static readGlobal() {
    // Accessed internally via 'ClassName.#identifier' or 'this.#identifier' in static context
    return Configuration.#globalConfig;
  }
}

const config = new Configuration();
console.log(config.readConfig()); // 'instance-level data'

// The following line would trigger an early SyntaxError during parsing,
// preventing the entire script from executing:
// console.log(config.#instanceConfig); 

Technical Characteristics

Lexical Scoping and Resolution The # symbol is an inherent part of the identifier name, not a modifier. The JavaScript engine resolves private identifiers lexically at compile-time. If the engine encounters a private identifier outside the lexical scope of the class that defines it, it throws an early SyntaxError during the parsing phase. This prevents the entire script or module from executing, rather than returning undefined or throwing a TypeError at runtime. Prototype Chain Isolation Private getters do not exist on the class prototype (Configuration.prototype). They are stored in internal slots associated with the specific instance (or the class constructor, for static getters). Because they bypass the prototype chain entirely, they cannot be overridden, mocked, or accessed via Object.getPrototypeOf(). Inheritance and Instance Installation Private getters are installed on the subclass instance during the super() call. While a subclass cannot lexically access the parent’s private identifier, the private getter is fully present on the subclass instance. Inherited public methods called on the subclass instance can successfully access and invoke the parent’s private getter.
class Parent {
  get #secret() { return 'hidden'; }
  
  reveal() {
    // Successfully accesses the private getter installed on the Child instance
    return this.#secret; 
  }
}

class Child extends Parent {
  // The following method would trigger an early SyntaxError during parsing,
  // preventing the entire script from executing:
  // attemptAccess() {
  //   return this.#secret; 
  // }
}

const child = new Child();
console.log(child.reveal()); // 'hidden'
Ergonomic Brand Checking Introduced in ES2022, the in operator can be used to safely check if an object possesses a specific private getter (i.e., verifying the object’s “private brand”). This mechanism allows developers to verify the presence of the private accessor without triggering a runtime TypeError, which would otherwise occur if attempting to access a non-existent private member on an arbitrary object.
class Validator {
  get #isValid() { return true; }

  static checkInstance(obj) {
    // Safely checks for the private brand without throwing
    if (#isValid in obj) {
      return obj.#isValid;
    }
    return false;
  }
}
Complementary Setters A private getter can be paired with a private setter using the exact same # identifier. If a private getter is defined without a corresponding private setter, any internal attempt to assign a value to that identifier will result in a runtime TypeError (Cannot set property #identifier of #<Class> which has only a getter).
Master JavaScript with Deep Grasping Methodology!Learn More