基本示例
// 命名函数
function add (x,y) {
return x+y
}
// 匿名函数
let myAdd = function (x,y) {
return x + y
}
let z = 100
function addToZ(x, y) {
return x+y+z
}
// add 和 myAdd 都是使用的内部变量
// addToZ 使用z是外部变量
函数示例
// 给函数添加类型
function add(x: number, y: number):number {
return x + y
}
// 完整的函数类型
// 函数类型必要的条件就是要写一个返回值类型,如果返回是一个空函数,那么也要明确指出返回的是空的。
// 函数式类型 主要有参数类型和返回值类型构成的。
// 就像addToZ这个方法,捕获一些不在函数中定义的变量,也不需要体现在函数体系里。实际上这些变量是函数的隐藏状态。并不是Api的组成部分。
let myAdd: (baseValue: number, increment: number) => number = function(x: number, y: number): number {
return x + y
}
// 推断类型 任意一边不写的话都可以自动推断。
let myAdd = function(x: number, y: number): number {
return x + y
}
// =>
let myAdd: (baseValue: number, increment: number) => number = function(x, y) {
return x + y
}
可选参数和默认参数
// typescript里面每个参数都是必须的 => 传递给一个函数参数的个数必须与函数期望的个数是一致的
// 例如
function buildName(firstName: string, lastName: string): string {
return firstName + ' ' + lastName
}
let result1 = buildName('Bob') // => 报错。 参数过少
let result2 = buildName('Bob', 'Adams', 'Sr.' ) // => 报错。 参数过多
let result3 = buildName('Bob', 'Adams') // => 正常
// 如何让其函数中的参数变成可选参数呢?
// =>
function buildName(firstName: string, lastName?:string): string {
if (lastName) {
return firstName + ' ' + lastName
} else {
return firstName
}
}
let result1 = buildName('Bob') // => 正常
let result2 = buildName('Bob', 'Adams', 'Sr.' ) // => 报错。 参数过多
let result3 = buildName('Bob', 'Adams') // => 正常
// 给参数添加默认值
// =>
function buildName(firstName: string, lastName = 'Simth'): string {
return firstName + ' ' + lastName
}
// let result1 = buildName('Bob') // => 正常
let result1 = buildName('Bob', undefined) // => 正常 Bob Simth
let result2 = buildName('Bob', 'Adams', 'Sr.' ) // => 报错。 参数过多
let result3 = buildName('Bob', 'Adams') // => 正常
// arguments 在typescript中多个参数如何表示呢? 剩余参数
function buildName(firstName: string, ...resOfName:string[]) : string {
return fisrtName
}
let result1 = buildName('Bob', undefined) // => 正常
let result2 = buildName('Bob', 'Adams', 'Sr.' ) // => 正常
let result3 = buildName('Bob', 'Adams') // => 正常
let buildNameFn: (fname:string, ...rest:string[]) => string = buildName
this
// JavaScript this 是在函数被调用的时候指定, 但是我们有时候是需要花点时间去弄清楚这个函数调用的上下文是什么(这个有时候不是轻易就能做到的事情)
// typeScript 会通知我们错误的使用this调用的地方。
// 举例: 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 ' + )
// Cannot read property '0' of undefined 。 this => undefined, 为什么this是undefined呢?
/**
* 1. cardPicker 是调用deck.createCardPicker 方法此时, 是属于 global。global 显然是没有 suits的属性的。
*/
// 那么我们如何解决这个问题呢?
// 我们采用 Es6 箭头函数就能解决这种问题。 因为 箭头函数的作用就是更改this指向问题。
// 其保存的是函数创建时候的this值。
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
}
}
}
}
// 在typescript中 this是推断Any的 是来自函数自变量表达式,所以this是不能正确的推断出this是一个正确的deck对象,
// 我们可以给出一个this参数, this参数是一个假的参数,它是出现在列表最前面。
interface Cord {
suit: string
cord: 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
}
}
}
}
// 如何给第三方库增加this的回调函数?
interface UIElement {
addClickListener(onclick: (this: void, e: Event) => void): void
}
class Handle {
type: string
onClickBad(this: Handle, e: Event) {
this.type = e.type
}
}
let h = new Handler()
let uiElement: UIElement = {
addClickListener() {
}
}
uiElement.addClickListener(h.onClickBad) // 这样引用会有问题吗?
// 会有问题, The 'this' types of each signature are incompatible. Type 'void' is not assignable to type 'Handler'
// 因为我们addClickListener this是void 而 Handle.onClickBad 中的this是Handle , 类型是不匹配的;
// 那么就把Handle其实中this类型更改成void
class Handle {
type: string
onClickBad(this: void, e: Event) {
this.type = e.type
}
}
// 显示上不报错, 但是在编译上还是会存在问题
// 因为this是void,那么this.type是访问不到的。
// 那么采用ES6箭头函数
class Handle {
type: string
onClickBad = (e: Event) => {
this.type = e.type
}
}
重载
// 因为 pickCard 定义的any, 所以没有 pickCard 参数是没有做类型检查的。 如何做类型检查呢? 就需要采用重载的方式
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)
let pickedCard2 = pickCard(15)
console.log('card: ' + pickedCard2.card + 'of' + pickedCard2.suit)