请问老师关于this规范

来源:3-19 函数 - this+ 重载

hy_wang

2019-04-28

请问一下老师关于this参数定义

interface Card {
  suit: string
  card: number
}

interface Deck {
  suits: string[]
  cards: number[]

  createCardPicker (this: Deck): () => Card
}

let deck: Deck = {
  suits: ['hearts', 'spades', 'clubs', 'diamonds'],
  cards: Array(52),
  // NOTE: 函数现在显式指定其被调用方必须是 deck 类型
  createCardPicker: function (this: Deck) {
    return function (this:Deck) {
      let pickedCard = Math.floor(Math.random() * 52)
      let pickedSuit = Math.floor(pickedCard / 13)

      return {suit: this.suits[pickedSuit], card: pickedCard % 13}
    }
  }
}

let cardPicker = deck.createCardPicker()
let pickedCard = cardPicker()

console.log('card: ' + pickedCard.card + ' of ' + pickedCard.suit)

我这样去定义了闭包中this要求this指向Deck,但是这个demo明明this并没有指向Deck而是Winodw,可是请问老师ts也没有提示错误。编译也通过。只是执行js报错。
请问老师关于this规范有什么作用?他什么时候会规范?

写回答

1回答

ustbhuangyi

2019-04-28

因为你只是显示的指明 this 的类型,但它实际的类型需要运行时来决定。记住声明并不能决定运行时的值。这里的正确姿势是内部使用箭头函数,而我们给 createCardPicker 的 this 加上 Deck 类型,是因为我们知道运行时的时候 createCardPicker 中的 this 是 Deck 类型,而 TypeScript 不知道,所以我们告诉它。

再举个极端例子,即使你显示给 createCardPicker 的 this 加上 Deck 类型,内部也使用箭头函数,但是如果运行时我们把 deck.createCardPicker 的 this 修改了,也会报错,你可以试试,在箭头函数的情况下,我们修改调用的代码。

let cardPicker = deck.createCardPicker.call({})
let pickedCard = cardPicker()

这样也会运行时报错,所以显示声明类型的意义是我们知道运行时应该是什么样的,它是来配合我们运行时用的,但它并不能决定我们运行时的行为,就 this 而言,它在运行时是什么值还是取决于我们如何去调用它。

1
4
hy_wang
谢谢老师~
2019-04-28
共4条回复

下一代前端开发语言 TypeScript从零重构axios

课程从零开始重构功能完整的JS库,是学习造轮子的不二之选!

2629 学习 · 877 问题

查看课程