静态成员与实例成员
静态成员与实例成员的区别
静态成员属于类本身,而实例成员属于类的实例。静态成员在类加载时初始化,实例成员在创建对象时初始化。静态成员通过类名访问,实例成员通过对象实例访问。
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
使用场景分析
静态成员适合用于:
- 工具类方法
- 常量或配置
- 实例间共享的数据
class MathUtils {
static PI = 3.14159;
static circleArea(radius: number) {
return this.PI * radius * radius;
}
}
console.log(MathUtils.circleArea(5));
实例成员适合用于:
- 对象特有的属性
- 依赖于对象状态的方法
- 需要多态行为的场景
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对静态成员有一些特殊处理:
- 静态成员可以声明为readonly
- 静态成员可以有访问修饰符
- 静态成员可以实现接口
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));
常见错误与陷阱
- 在静态方法中错误使用this访问实例成员
- 混淆静态成员和实例成员的访问方式
- 过度使用静态成员导致代码难以测试和维护
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
上一篇:接口实现与类类型