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 对象的构造函数。

相关推荐
white-persist1 小时前
Python实例方法与Python类的构造方法全解析
开发语言·前端·python·原型模式
新中地GIS开发老师1 小时前
Cesium 军事标绘入门:用 Cesium-Plot-JS 快速实现标绘功能
前端·javascript·arcgis·cesium·gis开发·地理信息科学
Superxpang2 小时前
前端性能优化
前端·javascript·vue.js·性能优化
Rysxt_2 小时前
Element Plus 入门教程:从零开始构建 Vue 3 界面
前端·javascript·vue.js
隐含2 小时前
对于el-table中自定义表头中添加el-popover会弹出两个的解决方案,分别针对固定列和非固定列来隐藏最后一个浮框。
前端·javascript·vue.js
大鱼前端2 小时前
Turbopack vs Webpack vs Vite:前端构建工具三分天下,谁将胜出?
前端·webpack·turbopack
你的人类朋友2 小时前
先用js快速开发,后续引入ts是否是一个好的实践?
前端·javascript·后端
知识分享小能手2 小时前
微信小程序入门学习教程,从入门到精通,微信小程序核心 API 详解与案例(13)
前端·javascript·学习·react.js·微信小程序·小程序·vue
子兮曰3 小时前
npm workspace 深度解析:与 pnpm workspace 和 Lerna 的全面对比
前端·javascript·npm