阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 静态成员与实例成员

静态成员与实例成员

作者:陈川 阅读数:8384人阅读 分类: TypeScript

静态成员与实例成员的区别

静态成员属于类本身,而实例成员属于类的实例。静态成员在类加载时初始化,实例成员在创建对象时初始化。静态成员通过类名访问,实例成员通过对象实例访问。

class Car {
  static wheels = 4; // 静态属性
  brand: string;    // 实例属性
  
  constructor(brand: string) {
    this.brand = brand;
  }
  
  static getWheels() {  // 静态方法
    return Car.wheels;
  }
  
  getBrand() {          // 实例方法
    return this.brand;
  }
}

// 访问静态成员
console.log(Car.wheels);  // 4
console.log(Car.getWheels()); // 4

// 访问实例成员
const myCar = new Car('Toyota');
console.log(myCar.brand);    // Toyota
console.log(myCar.getBrand()); // Toyota

静态成员的特点

静态成员与类绑定,而不是与实例绑定。所有实例共享同一个静态成员,修改静态成员会影响所有实例。

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

静态方法中不能使用this关键字访问实例成员,因为静态方法调用时可能还没有创建任何实例。

实例成员的特点

每个实例都有自己独立的实例成员副本,修改一个实例的成员不会影响其他实例。

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

实例方法可以通过this关键字访问当前实例的其他成员。

静态成员与实例成员的交互

静态成员和实例成员可以相互访问,但需要遵循特定规则。

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

使用场景分析

静态成员适合用于:

  1. 工具类方法
  2. 常量或配置
  3. 实例间共享的数据
class MathUtils {
  static PI = 3.14159;
  
  static circleArea(radius: number) {
    return this.PI * radius * radius;
  }
}

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

实例成员适合用于:

  1. 对象特有的属性
  2. 依赖于对象状态的方法
  3. 需要多态行为的场景
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!

TypeScript中的特殊考虑

TypeScript对静态成员有一些特殊处理:

  1. 静态成员可以声明为readonly
  2. 静态成员可以有访问修饰符
  3. 静态成员可以实现接口
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');

继承中的静态成员

静态成员也会被继承,子类可以访问父类的静态成员,也可以定义自己的静态成员。

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

设计模式中的应用

静态成员常用于实现设计模式,如单例模式:

class Database {
  private static instance: Database;
  
  private constructor() {
    // 初始化代码
  }
  
  public static getInstance(): Database {
    if (!Database.instance) {
      Database.instance = new Database();
    }
    return Database.instance;
  }
  
  query(sql: string) {
    // 执行查询
  }
}

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

性能考虑

静态成员在内存中只有一份拷贝,可以节省内存空间。实例成员每个对象都有自己的拷贝,适合存储对象特有的状态。

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;
  }
}

// 创建1000个粒子共享同一个GRAVITY值
const particles = Array(1000).fill(0).map((_, i) => new Particle(i, 0));

常见错误与陷阱

  1. 在静态方法中错误使用this访问实例成员
  2. 混淆静态成员和实例成员的访问方式
  3. 过度使用静态成员导致代码难以测试和维护
class BadExample {
  static sharedData = 'Shared';
  instanceData: string;
  
  constructor(data: string) {
    this.instanceData = data;
  }
  
  static badMethod() {
    // 错误:静态方法中访问实例成员
    // console.log(this.instanceData); 
  }
  
  instanceMethod() {
    // 正确:实例方法中访问静态成员
    console.log(BadExample.sharedData);
  }
}

高级用法:静态块

TypeScript 4.4+支持静态初始化块,用于复杂的静态成员初始化:

class Config {
  static apiUrl: string;
  static timeout: number;
  
  static {
    // 可以执行复杂的初始化逻辑
    this.apiUrl = process.env.API_URL || 'https://api.example.com';
    this.timeout = parseInt(process.env.TIMEOUT || '5000');
  }
}

console.log(Config.apiUrl);

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

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

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌