阿里云主机折上折
  • 微信号
Current Site:Index > static members and instance members

static members and instance members

Author:Chuan Chen 阅读数:8385人阅读 分类: TypeScript

The Difference Between Static Members and Instance Members

Static members belong to the class itself, while instance members belong to instances of the class. Static members are initialized when the class is loaded, whereas instance members are initialized when an object is created. Static members are accessed via the class name, and instance members are accessed through object instances.

class Car {
  static wheels = 4; // Static property
  brand: string;    // Instance property
  
  constructor(brand: string) {
    this.brand = brand;
  }
  
  static getWheels() {  // Static method
    return Car.wheels;
  }
  
  getBrand() {          // Instance method
    return this.brand;
  }
}

// Accessing static members
console.log(Car.wheels);  // 4
console.log(Car.getWheels()); // 4

// Accessing instance members
const myCar = new Car('Toyota');
console.log(myCar.brand);    // Toyota
console.log(myCar.getBrand()); // Toyota

Characteristics of Static Members

Static members are bound to the class, not to instances. All instances share the same static member, and modifying a static member affects all instances.

class Counter {
  static count = 0;
  
  constructor() {
    Counter.count++;
  }
  
  static getCount() {
    return Counter.count;
  }
}

const c1 = new Counter();
const c2 = new Counter();
console.log(Counter.getCount()); // 2

Static methods cannot use the this keyword to access instance members because static methods may be called before any instances are created.

Characteristics of Instance Members

Each instance has its own independent copy of instance members. Modifying an instance member of one object does not affect other instances.

class Person {
  name: string;
  
  constructor(name: string) {
    this.name = name;
  }
  
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

const p1 = new Person('Alice');
const p2 = new Person('Bob');
p1.greet(); // Hello, my name is Alice
p2.greet(); // Hello, my name is Bob

Instance methods can access other members of the current instance using the this keyword.

Interaction Between Static and Instance Members

Static and instance members can interact with each other, but specific rules must be followed.

class Logger {
  static logLevel = 'INFO';
  
  static setLogLevel(level: string) {
    Logger.logLevel = level;
  }
  
  log(message: string) {
    console.log(`[${Logger.logLevel}] ${message}`);
  }
}

const logger = new Logger();
logger.log('This is a test'); // [INFO] This is a test
Logger.setLogLevel('DEBUG');
logger.log('Debug message');  // [DEBUG] Debug message

Use Case Analysis

Static members are suitable for:

  1. Utility methods
  2. Constants or configurations
  3. Data shared among instances
class MathUtils {
  static PI = 3.14159;
  
  static circleArea(radius: number) {
    return this.PI * radius * radius;
  }
}

console.log(MathUtils.circleArea(5));

Instance members are suitable for:

  1. Object-specific properties
  2. Methods that depend on object state
  3. Scenarios requiring polymorphic behavior
class Animal {
  name: string;
  
  constructor(name: string) {
    this.name = name;
  }
  
  makeSound() {
    console.log('Some generic animal sound');
  }
}

class Dog extends Animal {
  makeSound() {
    console.log('Woof! Woof!');
  }
}

const myDog = new Dog('Buddy');
myDog.makeSound(); // Woof! Woof!

Special Considerations in TypeScript

TypeScript has some special handling for static members:

  1. Static members can be declared as readonly
  2. Static members can have access modifiers
  3. Static members can implement interfaces
interface Loggable {
  log(message: string): void;
}

class ConsoleLogger implements Loggable {
  private static instance: ConsoleLogger;
  
  private constructor() {}
  
  static getInstance() {
    if (!ConsoleLogger.instance) {
      ConsoleLogger.instance = new ConsoleLogger();
    }
    return ConsoleLogger.instance;
  }
  
  log(message: string) {
    console.log(message);
  }
}

const logger = ConsoleLogger.getInstance();
logger.log('Singleton pattern with static member');

Static Members in Inheritance

Static members are also inherited. Subclasses can access static members of the parent class and can define their own static members.

class Parent {
  static parentStatic = 'Parent static';
  
  static parentStaticMethod() {
    return 'Parent static method';
  }
}

class Child extends Parent {
  static childStatic = 'Child static';
  
  static childStaticMethod() {
    return `${this.parentStaticMethod()} + Child static method`;
  }
}

console.log(Child.parentStatic); // Parent static
console.log(Child.childStaticMethod()); // Parent static method + Child static method

Application in Design Patterns

Static members are often used to implement design patterns, such as the Singleton pattern:

class Database {
  private static instance: Database;
  
  private constructor() {
    // Initialization code
  }
  
  public static getInstance(): Database {
    if (!Database.instance) {
      Database.instance = new Database();
    }
    return Database.instance;
  }
  
  query(sql: string) {
    // Execute query
  }
}

const db1 = Database.getInstance();
const db2 = Database.getInstance();
console.log(db1 === db2); // true

Performance Considerations

Static members have only one copy in memory, saving memory space. Instance members have their own copy for each object, making them suitable for storing object-specific state.

class Particle {
  static GRAVITY = 9.8;
  x: number;
  y: number;
  
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
  
  update() {
    this.y += Particle.GRAVITY;
  }
}

// Create 1000 particles sharing the same GRAVITY value
const particles = Array(1000).fill(0).map((_, i) => new Particle(i, 0));

Common Mistakes and Pitfalls

  1. Incorrectly using this in static methods to access instance members
  2. Confusing the access methods for static and instance members
  3. Overusing static members, making code difficult to test and maintain
class BadExample {
  static sharedData = 'Shared';
  instanceData: string;
  
  constructor(data: string) {
    this.instanceData = data;
  }
  
  static badMethod() {
    // Error: Accessing instance members in a static method
    // console.log(this.instanceData); 
  }
  
  instanceMethod() {
    // Correct: Accessing static members in an instance method
    console.log(BadExample.sharedData);
  }
}

Advanced Usage: Static Blocks

TypeScript 4.4+ supports static initialization blocks for complex static member initialization:

class Config {
  static apiUrl: string;
  static timeout: number;
  
  static {
    // Can execute complex initialization logic
    this.apiUrl = process.env.API_URL || 'https://api.example.com';
    this.timeout = parseInt(process.env.TIMEOUT || '5000');
  }
}

console.log(Config.apiUrl);

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.