CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-core-js-pure

Modular standard library for JavaScript providing ECMAScript polyfills without global namespace pollution

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

symbol-management.mddocs/

Symbol Management

Symbol primitives and well-known symbols for creating unique identifiers, implementing protocols, and customizing built-in JavaScript behavior.

Capabilities

Symbol Constructor and Registry

Core Symbol functionality for creating unique identifiers and managing global symbol registry.

/**
 * Symbol constructor and static methods
 */
interface SymbolConstructor {
  /**
   * Creates a new unique Symbol
   * @param description - Optional string description for debugging
   */
  (description?: string | number): symbol;
  
  /**
   * Creates or retrieves a symbol from the global symbol registry
   * @param key - String key to identify the symbol
   */
  for(key: string): symbol;
  
  /**
   * Retrieves the key for a symbol in the global registry
   * @param symbol - Symbol to get the key for
   */
  keyFor(symbol: symbol): string | undefined;
}

Usage Examples:

import Symbol from 'core-js-pure/stable/symbol';

// Creating unique symbols
const sym1 = Symbol('description');
const sym2 = Symbol('description');
console.log(sym1 === sym2); // false - each symbol is unique

// Global symbol registry
const globalSym1 = Symbol.for('shared-key');
const globalSym2 = Symbol.for('shared-key');
console.log(globalSym1 === globalSym2); // true - same symbol from registry

console.log(Symbol.keyFor(globalSym1)); // 'shared-key'
console.log(Symbol.keyFor(sym1)); // undefined - not in global registry

// Using symbols as object keys
const obj = {};
const privateKey = Symbol('private');
obj[privateKey] = 'secret value';
obj.public = 'public value';

console.log(Object.keys(obj)); // ['public'] - symbol keys not enumerated
console.log(obj[privateKey]); // 'secret value'

Well-Known Symbols

Standard symbols that customize built-in JavaScript behavior and implement various protocols.

interface SymbolConstructor {
  /**
   * Symbol for async disposal in using declarations
   */
  readonly asyncDispose: unique symbol;
  
  /**
   * Symbol for async iteration protocol
   */
  readonly asyncIterator: unique symbol;
  
  /**
   * Symbol for disposal in using declarations
   */
  readonly dispose: unique symbol;
  
  /**
   * Symbol to customize instanceof behavior
   */
  readonly hasInstance: unique symbol;
  
  /**
   * Symbol to control Array.prototype.concat spreading
   */
  readonly isConcatSpreadable: unique symbol;
  
  /**
   * Symbol for iteration protocol
   */
  readonly iterator: unique symbol;
  
  /**
   * Symbol to customize String.prototype.match behavior
   */
  readonly match: unique symbol;
  
  /**
   * Symbol to customize String.prototype.matchAll behavior
   */
  readonly matchAll: unique symbol;
  
  /**
   * Symbol to customize String.prototype.replace behavior
   */
  readonly replace: unique symbol;
  
  /**
   * Symbol to customize String.prototype.search behavior
   */
  readonly search: unique symbol;
  
  /**
   * Symbol to specify constructor function for derived objects
   */
  readonly species: unique symbol;
  
  /**
   * Symbol to customize String.prototype.split behavior
   */
  readonly split: unique symbol;
  
  /**
   * Symbol to customize primitive conversion behavior
   */
  readonly toPrimitive: unique symbol;
  
  /**
   * Symbol to customize Object.prototype.toString behavior
   */
  readonly toStringTag: unique symbol;
  
  /**
   * Symbol to specify properties excluded from with statement
   */
  readonly unscopables: unique symbol;
}

Usage Examples:

import Symbol from 'core-js-pure/stable/symbol';

// Custom iterator implementation
class CountDown {
  constructor(start) {
    this.start = start;
  }
  
  [Symbol.iterator]() {
    let current = this.start;
    return {
      next() {
        if (current > 0) {
          return { value: current--, done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
}

const countdown = new CountDown(3);
console.log([...countdown]); // [3, 2, 1]

// Custom string tag for better debugging
class MyClass {
  [Symbol.toStringTag] = 'MyClass';
}

const instance = new MyClass();
console.log(Object.prototype.toString.call(instance)); // '[object MyClass]'

// Custom primitive conversion
class Temperature {
  constructor(celsius) {
    this.celsius = celsius;
  }
  
  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case 'number':
        return this.celsius;
      case 'string':
        return `${this.celsius}°C`;
      default:
        return this.celsius;
    }
  }
}

const temp = new Temperature(25);
console.log(+temp); // 25 (number conversion)
console.log(`${temp}`); // '25°C' (string conversion)
console.log(temp + 10); // 35 (default conversion to number)

Custom Protocol Implementation

Using symbols to implement custom protocols and behaviors.

/**
 * Examples of implementing custom protocols with symbols
 */

// Custom matcher protocol
interface Matcher {
  [Symbol.match](string: string): RegExpMatchArray | null;
  [Symbol.replace](string: string, replaceValue: string): string;
  [Symbol.search](string: string): number;
  [Symbol.split](string: string, limit?: number): string[];
}

// Custom species constructor
interface CustomArray<T> extends Array<T> {
  static [Symbol.species]: ArrayConstructor;
}

// Custom iteration protocol
interface CustomIterable<T> {
  [Symbol.iterator](): Iterator<T>;
}

// Custom async iteration protocol
interface CustomAsyncIterable<T> {
  [Symbol.asyncIterator](): AsyncIterator<T>;
}

Usage Examples:

import Symbol from 'core-js-pure/stable/symbol';

// Custom matcher that works with string methods
class WordMatcher {
  constructor(word) {
    this.word = word;
  }
  
  [Symbol.match](str) {
    const index = str.indexOf(this.word);
    return index !== -1 ? [this.word] : null;
  }
  
  [Symbol.replace](str, replacement) {
    return str.replace(this.word, replacement);
  }
  
  [Symbol.search](str) {
    return str.indexOf(this.word);
  }
  
  [Symbol.split](str) {
    return str.split(this.word);
  }
}

const matcher = new WordMatcher('hello');
const text = 'Say hello to the world';

console.log(text.match(matcher)); // ['hello']
console.log(text.replace(matcher, 'hi')); // 'Say hi to the world'
console.log(text.search(matcher)); // 4
console.log(text.split(matcher)); // ['Say ', ' to the world']

// Custom async iterable
class AsyncRange {
  constructor(start, end, delay = 100) {
    this.start = start;
    this.end = end;
    this.delay = delay;
  }
  
  [Symbol.asyncIterator]() {
    let current = this.start;
    const end = this.end;
    const delay = this.delay;
    
    return {
      async next() {
        if (current <= end) {
          await new Promise(resolve => setTimeout(resolve, delay));
          return { value: current++, done: false };
        }
        return { done: true };
      }
    };
  }
}

// Usage with for-await-of
const asyncRange = new AsyncRange(1, 3, 500);
for await (const num of asyncRange) {
  console.log(num); // Prints 1, 2, 3 with 500ms delay between each
}

instanceof Customization

Using Symbol.hasInstance to customize instanceof behavior.

/**
 * Custom instanceof behavior using Symbol.hasInstance
 */
interface Constructor {
  [Symbol.hasInstance](instance: any): boolean;
}

Usage Examples:

import Symbol from 'core-js-pure/stable/symbol';

// Custom instanceof behavior
class Collection {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance) || 
           instance instanceof Set || 
           instance instanceof Map;
  }
}

console.log([] instanceof Collection); // true
console.log(new Set() instanceof Collection); // true
console.log(new Map() instanceof Collection); // true
console.log({} instanceof Collection); // false

// Type checking utility
class TypeChecker {
  static [Symbol.hasInstance](instance) {
    return typeof instance === 'string' || 
           typeof instance === 'number' || 
           typeof instance === 'boolean';
  }
}

console.log('hello' instanceof TypeChecker); // true
console.log(42 instanceof TypeChecker); // true
console.log(true instanceof TypeChecker); // true
console.log({} instanceof TypeChecker); // false

Array Concat Spreadability

Controlling how objects behave when used with Array.prototype.concat.

/**
 * Control concat spreading behavior
 */
interface ConcatSpreadable {
  [Symbol.isConcatSpreadable]: boolean;
}

Usage Examples:

import Symbol from 'core-js-pure/stable/symbol';

// Array-like object that spreads in concat
const arrayLike = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3,
  [Symbol.isConcatSpreadable]: true
};

console.log([1, 2].concat(arrayLike)); // [1, 2, 'a', 'b', 'c']

// Array that doesn't spread
const nonSpreadingArray = ['x', 'y'];
nonSpreadingArray[Symbol.isConcatSpreadable] = false;

console.log([1, 2].concat(nonSpreadingArray)); // [1, 2, ['x', 'y']]

// Custom collection class
class CustomCollection extends Array {
  constructor(...items) {
    super(...items);
    // Control whether instances spread in concat
    this[Symbol.isConcatSpreadable] = false;
  }
}

const collection = new CustomCollection('a', 'b');
console.log([1, 2].concat(collection)); // [1, 2, CustomCollection(['a', 'b'])]

Common Patterns

Private Object Properties

Using symbols to create private-like properties that won't conflict with string keys.

import Symbol from 'core-js-pure/stable/symbol';

// Private properties using symbols
const _private = Symbol('private');
const _secret = Symbol('secret');

class SecureClass {
  constructor(publicData, privateData) {
    this.public = publicData;
    this[_private] = privateData;
    this[_secret] = 'top secret';
  }
  
  getPrivate() {
    return this[_private];
  }
  
  static getSecret(instance) {
    return instance[_secret];
  }
}

const obj = new SecureClass('public info', 'private info');
console.log(obj.public); // 'public info'
console.log(obj.getPrivate()); // 'private info'
console.log(Object.keys(obj)); // ['public'] - symbols not enumerated

Protocol Implementation Framework

Creating a framework for implementing custom protocols.

import Symbol from 'core-js-pure/stable/symbol';

// Protocol registry
const protocols = new Map();

const defineProtocol = (name, symbol) => {
  protocols.set(name, symbol);
  return symbol;
};

const implementsProtocol = (obj, protocolName) => {
  const symbol = protocols.get(protocolName);
  return symbol && typeof obj[symbol] === 'function';
};

// Define custom protocols
const Serializable = defineProtocol('Serializable', Symbol('Serializable'));
const Comparable = defineProtocol('Comparable', Symbol('Comparable'));
const Cloneable = defineProtocol('Cloneable', Symbol('Cloneable'));

// Implement protocols
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  [Serializable]() {
    return JSON.stringify({ name: this.name, age: this.age });
  }
  
  [Comparable](other) {
    return this.age - other.age;
  }
  
  [Cloneable]() {
    return new Person(this.name, this.age);
  }
}

const person = new Person('Alice', 30);
console.log(implementsProtocol(person, 'Serializable')); // true
console.log(person[Serializable]()); // '{"name":"Alice","age":30}'

Cross-Realm Communication

Using global symbols for cross-realm (iframe, worker) communication.

import Symbol from 'core-js-pure/stable/symbol';

// Global symbols work across different JavaScript realms
const SHARED_PROTOCOL = Symbol.for('app.shared.protocol');
const MESSAGE_TYPE = Symbol.for('app.message.type');

// In main window
const createMessage = (type, data) => ({
  [MESSAGE_TYPE]: type,
  data,
  timestamp: Date.now()
});

// In worker or iframe (different realm)
const handleMessage = (message) => {
  const type = message[MESSAGE_TYPE];
  switch (type) {
    case 'user-action':
      return processUserAction(message.data);
    case 'system-event':
      return processSystemEvent(message.data);
  }
};

// Protocol works across realms because symbols are global
const userMessage = createMessage('user-action', { action: 'click' });
handleMessage(userMessage); // Works even in different realm

docs

array-operations.md

collection-types.md

error-types.md

index.md

iterator-helpers.md

math-utilities.md

object-methods.md

promise-utilities.md

reflection-api.md

string-processing.md

symbol-management.md

typedarray-operations.md

web-apis.md

tile.json