13面向对象之class下

一. 成员可见性

  • 有以下几种
    • public 类外可见
    • private 类内可见
ts 复制代码
class Person {
  private friend?: Person; //
  constructor(public name: string, friend?: Person) {
    this.friend = friend;
  }
  xxx() {
    this.friend; // 内部是可以用
  }
}

const p = new Person('Alice');
p.friend; //默认是public可见,如果前面加了private则没有这个属性,会报错
  • protected 子类可见
ts 复制代码
class Person {
  protected friend?: Person; //
  constructor(public name: string, friend?: Person) {
    this.friend = friend;
  }
}

const p = new Person('Alice');

class User extends Person {
  declare friend: User; // 重写一个属性的类型
  constructor(public id: number, name: string, friend?: User) {
    super(name, friend);
  }
  xxx() {
    this.friend; // 子类可以用,可以认为只有这个家族可以用
  }
}
  • 真私有属性,以上的private编译成js之后没有类型,依然可以调用,前面+#就是真正的私有属性,编译成js之后不会被擦除,因为这其实是js的语法
ts 复制代码
class Person {
  #friend?: Person; //
  constructor(public name: string, friend?: Person) {
    this.#friend = friend;
  }
}

二. static属性与static block

ts 复制代码
class Person {
  static xxx = 1;
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

Person.xxx; // 这就是Person上的属性,其实就是Person.xxx = 1,这个叫做类属性或者静态属性 
  • 需要注意static name会报错,同样也不能声明 prototype, length 等函数本身有的属性
ts 复制代码
class Person {
  static name = 1; // 会报错,因为js的类是靠函数模拟的,函数本身就有name的属性
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
  • static可以用来表达类的共有属性,通过类属性来表达原型上共有属性的概念
ts 复制代码
class Person {
  static 种族 = '人类'; // 这个种族是所有对象共有的属性
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
  • static block,假如有需求,需要在类里面获取某个计数
js 复制代码
class Foo {
  static #count = 0;
  static {
    // 意思是这段代码在类创建的时候使用,初始化私有属性
    const count = loadFromLocalStorage() || 0;
    Foo.#count += count;
  }
  constructor() {
    console.log(Foo.#count);
  }
}

三. 类加泛型

  • 例子一
ts 复制代码
class Hash<K, V> {
  map: Map<K, V> = new Map();
  set(key: K, value: V) {
    this.map.set(key, value);
  }
  get(key: K) {
    return this.map.get(key);
  }
}

const h = new Hash<string | number, string | number>();

h.set('name', 'hi');
h.get('name');

h.set([1, 2], 'hi'); // 会报错
  • 例子二,继承
ts 复制代码
class Hash<K, V> extends Map<K, V> {
  destroy() {
    this.clear();
  }
}

四. class表达式,其实就是匿名class

ts 复制代码
const Rectangle = class {
  constructor(public height: number, public width: number) {}
  area() {
    return this.height * this.width;
  }
};
const r = new Rectangle(100, 200);

五. 抽象类(不常用)

  • 为什么要有抽象类
    • interface只写类型,class又写类型又写实现,而抽象类就是为了实现一部分
ts 复制代码
abstract class C {
  // 也可以全部不实现,当成interface
  abstract name: string;
  age: number;
  constructor(age: number) {
    this.age = age;
  }
  abstract a(): number;
  abstract b(): number;
}

class D extends C {
  name: string;
  constructor(name: string) {
    super(18);
    this.name = name;
  }
  a() {
    return 1;
  }
  b() {
    return 2;
  }
}

const c = new D('Frank')

六. 把类当作参数

ts 复制代码
class Person {
  constructor(public name: string) {}
}

// 方式一
function f(X: typeof Person) {
  const p = new X('frank');
  console.log(p.name);
}

f(Person);

function ff(x: string) {
  console.log(x);
}
ff('hello'); // 我们可以发现,函数上的类型要比传入的类型范围大

// 方式二
function f2(X: new (name: string) => Person) {
  const p = new X('frank');
  console.log(p.name);
}

// f2(Person)的本质 (name: string) => obj

function ff2(x: (name: string) => string) {
  // ff2 类比f2
  x('frank');
}
ff2((name) => 'hello'); // 下面的返回值实际上比上面的高一点

第二种方式比较难理解,function f2(X: new (name: string) => Person)这是函数 f2 的定义。它接受一个参数 X,其中 X 的类型是一个构造函数,该构造函数接受一个名为 name 的字符串参数,并且该构造函数的返回类型必须是 Person

const p = new X('frank')在函数内部,它使用构造函数 X 创建了一个新的对象 p,并传递了 frank 作为参数。这段代码的关键点在于它使用了 TypeScript 中的函数类型签名来限定参数 X 的类型,确保 X 是一个能够创建 Person 对象的构造函数。

相关推荐
GIS程序媛—椰子40 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0011 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
木舟10091 小时前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤43911 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢1 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
黎金安1 小时前
前端第二次作业
前端·css·css3
啦啦右一1 小时前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习
半开半落2 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt