美文网首页
TypeScript 函数中的 this 参数

TypeScript 函数中的 this 参数

作者: 年轻人多学点 | 来源:发表于2021-02-11 23:10 被阅读0次

从 TypeScript 2.0 开始,在函数和方法中我们可以声明 this 的类型,实际使用起来也很简单,比如:

function sayHello(this: void) {
  // this: void:表示在函数体内不允许使用this
}

在上面的 sayHello 函数中,this 参数是伪参数,它位于函数参数列表的第一位。为什么说 this 参数是伪参数呢?因为以上的 sayHello 函数经过编译后,并不会生成实际的参数,该函数编译成 ES5 后的代码如下:

function sayHello() {
  // this: void:表示在函数体内不允许使用this
}

那么在实际开发中,this 参数有什么用呢?下面我们来详细介绍一下 this 参数的一些应用场景。

一、未使用 this 参数

class Rectangle {
  private w: number;
  private h: number;

  constructor(w: number, h: number) {
    this.w = w;
    this.h = h;
  }

  getArea() {
    return () => {
      return this.w * this.h;
    };
  }
}

以上代码中,我们定义了一个 Rectangle 长方形类,该类中包含了两个私有的 w 和 h 属性,分别表示长方形的宽度和高度,此外还有一个 getArea 方法用于获取长方形的面积。在 getArea 方法中我们没有使用 this 参数,此时 this 的类型是 this,如下图所示:

without-this-param

二、使用 this 参数

class Rectangle {
  private w: number;
  private h: number;

  constructor(w: number, h: number) {
    this.w = w;
    this.h = h;
  }

  getArea(this: Rectangle) {
    return () => {
      return this.w * this.h;
    };
  }
}

与前面定义的 Rectangle 长方形类不同,在 getArea 方法中,我们使用了 this 参数,之后 this 的类型是 Rectangle 类型,如下图所示:

with-this-param
Rectangle 长方形类 getArea 方法中的 this 入参只是作为一个形式上的参数,供 TypeScript 做静态检查时使用,编译后并不会生成实际的入参。

三、禁止使用 this

有些时候,我们希望在方法中,禁止用户使用 this。针对这种需求,你可以设置 this 参数的类型为 void

class Rectangle {
  private w: number;
  private h: number;

  constructor(w: number, h: number) {
    this.w = w;
    this.h = h;
  }

  getArea(this: void) {
    return () => {
      return this.w * this.h;
    };
  }
}

以上代码会提示以下异常:

Property 'w' does not exist on type 'void'.
Property 'h' does not exist on type 'void'.

四、回调函数中 this
前端开发者日常经常需要跟回调函数打交道,比如在页面中监听用户的点击事件,然后执行对应的处理函数,具体示例如下:

const button = document.querySelector("button");
// ?. -> TS 3.7引入的可选链
button?.addEventListener("click", handleClick);

function handleClick() {
  console.log("Clicked!");
  // 'this' implicitly has type 'any' because it does not have a type annotation.
  this.removeEventListener("click", handleClick);
}

对于以上代码,TypeScript 编译器会有以下错误提示:this 隐式具有 any 类型,这是因为它没有类型注解。为了解决这个问题,我们就可以显式指定 this 参数的类型:

const button = document.querySelector("button");
button?.addEventListener("click", handleClick);

function handleClick(this: HTMLElement) {
  console.log("Clicked!");
  this.removeEventListener("click", handleClick);
}

除此之外,TypeScript 2.0 还增加了一个新的编译选项:--noImplicitThis,表示当 this 表达式值为 any 类型的时候,生成一个错误信息。


如果你来自传统的强类型语言,可能会很熟悉 void 的概念:一种类型,告诉你函数和方法在调用时不返回任何内容。

void 作为运算符存在于 JavaScript 中,而作为基本类型存在于 TypeScript 中。在这两个世界中,void 的工作机制与大多数人习惯的有点不同。

JavaScript 中的 void

JavaScript 中的 void 是一个运算符,用于计算它旁边的表达式。无论评估哪个表达式,void总是返回undefined。

1
let i = void 2; // i === undefined
我们为什么需要这样的东西?首先在早期,人们能够覆盖 undefined 并给它一个实际值。 void 总是返回 real undefined。

其次,这是一种调用立即调用函数的好方法:

1
2
3
void function() {
console.log('What')
}()
所有这些都没有污染全局命名空间:

1
2
3
4
5
6
7
8
void function aRecursion(i) {
if(i > 0) {
console.log(i--)
aRecursion(i)
}
}(3)

console.log(typeof aRecursion) // undefined
由于 void 总是返回 undefined,而 void 总是计算它旁边的表达式,你有一个非常简洁的方法从函数返回而不返回一个值,但仍然调用一个回调例如:

1
2
3
4
5
6
// returning something else than undefined would crash the app
function middleware(nextCallback) {
if(conditionApplies()) {
return void nextCallback();
}
}
这让我想到了 void 最重要的通途:它是你程序的安全门。当你的函数总是应该返回 undefined 时,你可以确保始终如此。

1
button.onclick = () => void doSomething();
TypeScript 中的 void

TypeScript 中的 void 是 undefined 的子类型。 JavaScript 中的函数总是返回一些东西。要么它是一个值,要么是 undefined:

1
2
3
function iHaveNoReturnValue(i) {
console.log(i)
} // returns undefined
因为没有返回值的函数总是返回 undefined,而 void 总是在 JavaScript 中返回 undefined,TypeScript 中的void 是一个正确的类型,告诉开发人员这个函数返回 undefined:

1
declare function iHaveNoReturnValue(i: number): void
void 作为类型也可以用于参数和所有其他声明。唯一可以传递的值是 undefined:

1
2
3
4
5
declare function iTakeNoParameters(x: void): void

iTakeNoParameters() // 👍
iTakeNoParameters(undefined) // 👍
iTakeNoParameters(void 2) // 👍
所以 void 和 undefined 几乎是一样的。虽然有一点点不同,但这种差别很大:作为返回类型的 void 可以用不同的类型替换,以允许高级回调模式:

1
2
3
4
5
6
7
8
9
10
11
12
function doSomething(callback: () => void) {
let c = callback() // at this position, callback always returns undefined
//c is also of type undefiend
}

// this function returns a number
function aNumberCallback(): number {
return 2;
}

// works 👍 type safety is ensured in doSometing
doSomething(aNumberCallback)
如果你想确保传递只返回 undefined 的函数(如“nothing”),请确保调整你的回调方法签名:

1
2
3
4
5
6
7

  • function doSomething(callback: () => void) {
  • function doSomething(callback: () => undefined) { /* ... */ }

function aNumberCallback(): number { return 2; }

// 💥 types don't match
doSomething(aNumberCallback)

大概大部分时间你都能和 void 很好的相处。

`

相关文章

  • typescript语法

    参考:typescript参考1 typescript参考2 函数参数类型定义 声明函数参数默认值 ...

  • TypeScript 函数中的 this 参数

    从 TypeScript 2.0 开始,在函数和方法中我们可以声明 this 的类型,实际使用起来也很简单,比如:...

  • typeScript学习02

    typescript中的函数 ts中函数定义 ts中函数的传参 ts中的函数的可选参数(js中函数的形参和实参可以...

  • TypeScript中的函数

    TypeScript中的函数相比ES5新增了一些功能,比如规范了传参的类型,函数返回值的类型,可选参数, 默认参数...

  • TypeScript类型补充(三)

    1. 函数的参数类型 函数是JavaScript非常重要的组成部分,TypeScript允许我们指定函数的参数和返...

  • 6个 TS新特性

    在构造函数中直接定义属性 Typescript 中可以通过构造函数的参数直接定义属性,我们来先看早期的做法: 采用...

  • TypeScript 函数-可变参数

    参考网址:https://www.tslang.cn/docs/handbook/functions.html 剩...

  • function

    pattern 1 patter 2 pattern 3 可选参数 在 TypeScript 函数里,如果我们定义...

  • TypeScript-可选默认参数、剩余参数

    可选默认参数 TypeScript里的每个函数参数都是必须的。 这不是指不能传递 null或undefined作为...

  • TypeScript基础入门 - 函数 - 可选参数和默认参数

    转载 TypeScript基础入门 - 函数 - 可选参数和默认参数 项目实践仓库 为了保证后面的学习演示需要安装...

网友评论

      本文标题:TypeScript 函数中的 this 参数

      本文链接:https://www.haomeiwen.com/subject/kmlqxltx.html