引言:本周在写单元测试时,调用M层中函数时发生了报错does not exist on type 'typeof ***Service,于是便有了下面这些内容。

以下是test.service.ts中的代码

export class TestService {
  private url = 'test';

  constructor(private httpClient: HttpClient) {
  }

  /**
   * 获取以name为查询关键字的前20项记录
   * @param name 单位名称
   */
  getTop20ByNameContains(name: string): void {
  
  }

  findTopNameContains(name: string): void {
  }
  /**
   * 新增
   * @param name 名称
   */
  save(name: string): Observable<Cult> {
    return this.httpClient.post<Cult>(this.url, {name})
      .pipe(map(value => new Cult(value)));
  }
  /**
   * 更新最后一次使用时间
   * @param id ID
   */
  updateLastUsedTime(id: number): Observable<void> {
    return this.httpClient.patch<void>(`${this.url}/updateLastUsedTime/${id}`, {});
  }
  public static function():void{
    console.log('public static function');
  };
}

之后我先尝试在C层中调用,发现static方法只能在类中调用,不能在实例化的对象中调用,这是和我们认知中的C语言不同的地方。

那么此时我们又会想要知道在调用static方法时会不会生成一个临时对象呢,也就是说会不会调用service中的构造函数。

经过测试并不会调用他自己的构造函数,也就是说并不会生成所谓的临时对象。

除此之外,我们还想要了解publicpriviteprotected等属性和C语言中又有那些不同呢?
就比如最简单的,我们都知道在C中如果不声明函数的类型,那么它就默认为private类型,那么在ts中呢。

export class TestComponent implements OnInit {

  constructor(private testService: TestService) {

  }

  ngOnInit(): void {
    TestService.function();
    this.testService.getTop20ByNameContains('');
    return ;
  }
  private add(): void{
  };
  test(): void{
    this.add();
    this.pro();
  }
  protected pro(): void{

  }
}

像这样定义TestComponent时我们可以在单元测试中进行如下操作:

fit('should create', () => {
    component.test();
    component.public();
    component.ngOnInit();
    expect(component).toBeTruthy();
  });

但是当我们调用add()或是pro()时就会发生报错。
也就是说如果不声明类型的话TS就会默认为public类型。并且protected类型也不可直接在单元测试中调用,那么在它的子类中和C语言中的又会有区别呢?

export class Test1Component extends TestComponent{
  ngOnInit(): void {
    this.test();     //public
    this.public();   //public
    this.pro();      //protected
    this.ngOnInit(); //public
    return ;
  }
}

在子类中可以调用父类中的protected,public的函数,这里和c是相同的,在子组件的单元测试中调用的话就只能调用public类型函数,这也可以和C语言中类内类外调用作类比。

在调用M层方法时也就相当于在类外调用即只能调用类型为public类型函数。

此外就算在构造函数中多次构造同一Service其构造函数也只会执行一次

constructor(public testService: TestService,public testService2: TestService,public testService3: TestService) {}

下面的是M层中的构造函数

  constructor(private httpClient: HttpClient) {
    console.log('service constructor');
  }

此时控制台中输出为

service constructor

特别的在C层中引入M层时如果不添加public,private,protected等词修饰时在C层中并不能正常调用。例如这样

constructor( testService: TestService) {

  }

会发生报错:
组件中不存在该service,其中有条快捷修复是增加[x: string]: any;但这也只是治标不治本,只是webstorm中没有报错,还是不能正常调用该函数。

`[x: string]: any;`是一个索引签名,即访问对象所用的键为`string`,其返回值为any,把他声明在class中就可以起到如上作用。其次值得一提的是签名的键只能有一个,而其返回值类型可以规定有多种,例如可以这样: `[key: string]: string | number | boolean;`

下面是索引签名的实际应用

const salary1 = {
      baseSalary: 100_000,
      extraSalary: 20_000
    };
const salary2 = {
      daylySalary: 100_000,
      monthlySalary: 300_000
}

function totalSalary(salary:{[x:string]: number}) {
      let totalSalary = 0;
        for (const string in salary) {
        totalSalary += salary[string];
      }
      return totalSalary;
    }

想要从不同的对象中获取同一类数值并进行同一种运算时在声明参数时可以用到。


李明
441 声望19 粉丝