# TypeScript 函数式编程

# 1. 函数作为一等公民(与 number 同值):

# 变量类型可以是函数

let a:(a: number, b: number) => number
a = (a:number, b:number)=>(a+b)

# 值(literal)可以是函数

let add  = function(a: number, b:number):number {
    return a + b
}

console.log(add(1, 2))  //3

# 对象的字段可以是函数

const emp1 = {
    name: 'hedon',
    salary: 10000,
    increaseSalary: function(p: number){
        this.salary += p
    },
}

# 函数的参数可以是函数

let a  = [5, 2, 1, 11, 23, 4, 5, 0, 64, 8]

// 按照字典顺序排序
a.sort()
console.log(a)  // [0, 1, 11, 2, 23, 4, 5, 5, 64, 8] 

// 按照数值大小排序

// 函数
a.sort((a: number, b: number) => {
    return  a-b
})
// lambda: 箭头函数
a.sort((a: number, b: number) => a-b)
a.sort((a, b) => a -b)
a.sort(() => )
console.log(a) // [0, 1, 2, 4, 5, 5, 8, 11, 23, 64] 

# 函数的返回值可以是函数

function createComparetor(smallFirst: boolean): (a:number, b:number) => number{
    if(smallFirst){
        return (a,b) => a-b
    }else{
        return (a,b) => b-a
    }
}

console.log(createComparetor(true)(1,2))        //-1
console.log(createComparetor(false)(1,2))       //1

# 2. 高阶函数

  • 函数的参数可以是函数;
  • 函数的返回值可以是函数;
function loggingComparer(f: (a:number, b:number) => number) {
    return (a: number, b: number) =>{
        console.log('logging: ', a, b)
        return f(a, b)
    }
}

console.log(loggingComparer((a: number, b :number) => (a-b))(1,2))
console.log(loggingComparer((a: number, b :number) => (a+b))(1,2))
console.log(loggingComparer((a: number, b :number) => (a*b))(1,2))

# 3. 函数闭包

非闭包版本:

  • 需要维护全局变量 compCount
let compCount = 0
// 比较器
function createComparer(p: {smallerFirst: boolean}) {
    if(p.smallerFirst){
        return (a:number, b:number) => a - b
    }else{
        return (a:number, b:number) => b - a
    }
}

// 比较器增强器
function loggingComparer(comp: (a: number, b:number) => number) {
    return (a:number, b: number) => {
        console.log(`comparing: {a} with {b}`)
        compCount ++
        return comp(a, b)
    }
}

let a = [4,2,6,23,11,9,0,-2,34]


// 比较
const comp = createComparer({smallerFirst: true})
a.sort(loggingComparer(comp))
console.log(a)
console.log(`compare count: ${compCount}`)

闭包版本:

// 比较器
function createComparer(p: {smallerFirst: boolean}) {
    if(p.smallerFirst){
        return (a:number, b:number) => a - b
    }else{
        return (a:number, b:number) => b - a
    }
}

// 比较器增强器
function loggingComparer(
    logger :(a: number, b:number) => void,
    comp: (a: number, b:number) => number) {
    return (a:number, b: number) => {
        logger(a,b)
        return comp(a, b)
    }
}

// 函数闭包
function processArray(a: number[]){
    let compCount = 0
    
    // logger 是一个闭包,可以延长 compCount 的生命周期
    // compCount 是一个自由变量
    const logger = (a: number, b: number) => {
        console.log(`compare ${a} with ${b}`)
        compCount ++
    }
    // 比较
    const comp = createComparer({smallerFirst: true})
    a.sort(loggingComparer(logger,comp))
    // 输出比较次数
    console.log(`compare count: ${compCount}`)
}

let a = [4,2,6,23,11,9,0,-2,34]

// 比较
processArray(a)
console.log(a)

# 4. 部分应用函数

示例 1:

// 部分函数应用
function partiallyApply(
    // 双参数函数
    f: (a:number, b:number) => number,
    a: number) {
    
    // 返回一个单参数函数
    // 这样你可以先给我 a
    // 返回再通过我这个返回的函数,后面有了 b 再给我
    return (b: number) => f(a,b)
}

// 加法
function add(a: number, b:number):number {
    return a + b
}

// 现在只有 a,还没有拿到 b
let a = 10
const partFunc = partiallyApply(add, a)

// 现在有了 b 了
let b  = 3
const result = partFunc(b)

// 结果
console.log(result)     // 13

示例 2:

// 判断一个数字是不是好数字
function isGoodNumber(gooFactor: number, v: number){
    return v % gooFactor === 0
}

// 过滤器
function filterArray(a: number[], f: (v: number) => boolean){
    return a.filter(f)
}

// START CONFIG
const GOOD_FACTOR = 2
// END CONFIG


const a  = [1, 2, 3, 4, 5, 6, 7, 8, 9]

// 部分应用函数:
//  1. 已经有了 GOOD_FACTOR,但是还缺少 v
//  2. 这个时候可以用部分应用函数:我先给了 GOOD_FACTOR
//  3. 然后再借一个 v,它会自动从 a 中拿出每一个元素
console.log(filterArray(a, (v) => isGoodNumber(GOOD_FACTOR, v)))
上次更新: 11/5/2021, 11:32:42 AM