JavaScript里面的this的值是被调用才被确定的,需要弄清楚函数调用的上下文
let deck = { suits: ['hearts', 'spades', 'clubs', 'diamonds'], cards: Array(52), createCardPicker: function() { return function () { 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指向global //改进的方法可以把上述函数改成箭头函数
let deck = { suits: ['hearts', 'spades', 'clubs', 'diamonds'], cards: Array(52), createCardPicker: function() { return ()=> { 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在这个函数类型检测里面是any,有一个方法是把这个this直接指向void,在函数里面这个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), createCardPicker: function(this: Deck) { return ()=> { 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在回调函数里面的指向
interface UIElement { addClickListener(onclick: (this: void, e: Event) => void) :void } class Handler { type: string onclickBad(this: Handler, e: Event){ this.type = e.type } } let h = new Handler() let uiElement: UIElement = { addClickListener(){ } } uiElement.addClickListener(h.onclickBad)//报错this类型不兼容,因为上面我们定义的this是void //如果我们既想满足接口的约定,又想使用this.type = e.type,可以使用箭头函数 // class Handler { // type: string // onclickBad = (e: Event)=>{ // this.type = e.type // } // }
重载
let suits = ['hearts', 'spades', 'clubs', 'diamonds'] //这个函数由于传入的值没有指定,导致如果传入字符串也不会报错 //所以我们要做一些重载的约束 function pickCard (x: {suit: string; card: number}[]): number function pickCard (x: number): {suit: string; card: number} //这样就可以做正确的类型检查了 //我们要把最正确重载的定义放在最前面 function pickCard(x): any{ if (Array.isArray(x)){ let pickedCard = Math.floor(Math.random() * x.length) return pickedCard } else if (typeof x === 'number') { let pickedSuit = Math.floor(x / 13) return {suit: suits[pickedSuit], card: x % 13} } } let myDeck = [ {suit: 'diamonds', card: 2}, {suit: 'spades', card: 10}, {suit: 'hearts', card: 4} ] let pickedCard1 = myDeck[pickCard(myDeck)]; console.log('card: ' + pickedCard1.card + ' of ' + pickedCard1.suit) //card: 4 of hearts let pickedCard2 = pickCard(15) console.log('card: ' + pickedCard2.card + ' of ' + pickedCard2.suit) //card: 2 of spades
2019-05-28 17:45:28