请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

请问老师关于this规范

请问一下老师关于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 23:15:40

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

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

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

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

1 回复 有任何疑惑可以回复我~
  • 提问者 hy_wang #1
    请问老师您这段话的意思我可以理解成,ts中指明this的指向其实ts是不会帮我检测的。它只是相当于我告诉我自己这里的this应该指向哪里,ts编译时候如果指向不正确也并不会报错。只有运行js时候才会因为this指向不同发生错误报错。请问老师我这样理解对吗,就是简单来说这里指定this仅仅是我给自己看,ts并不会检测
    回复 有任何疑惑可以回复我~ 2019-04-28 23:22:18
  • 提问者 hy_wang #2
    我好像理解错了,我告诉TS this的指向,他就会帮我检查this指向中是否存在相应的方法或者属性。它也仅仅检查我们告诉他this指向的对象中对应的方法,属性是否在this上是否存在。
    回复 有任何疑惑可以回复我~ 2019-04-28 23:25:40
  • ustbhuangyi 回复 提问者 hy_wang #3
    是这样的,很多时候,我们都会告诉 TypeScript 编译器一些东西,比如后续还有类型断言,非空断言,都是类似的意思~
    回复 有任何疑惑可以回复我~ 2019-04-28 23:27:31

相似问题

登录后可查看更多问答,登录/注册

问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信