高阶函数
什么是高阶函数
- 高阶函数 (Higher-order function)
- 可以把函数作为参数传递给另一个函数
- 可以把函数作为另一个函数的返回结果
- 函数作为参数
模拟 forEach
// forEach
function forEach (array, fn) {
for (let i = 0; i < array.length; i++) {
fn(array[i])
}
}
let arr = [1, 3, 4, 7, 8]
forEach(arr, function (item) {
console.log(item)
})
模拟 filter
// filter
function filter (array, fn) {
let results = [] for (let i = 0; i < array.length; i++) {
if (fn(array[i])) {
results.push(array[i])
}
}
return results
}
let arr = [1, 3, 4, 7, 8]
// 过滤取偶数
let returnArr = filter(arr, function (item) {
return item % 2 === 0
})
console.log(returnArr)
- 函数作为返回值
function makeFn () {
let msg = 'Hello function'
return function () {
console.log(msg)
}
}
makeFn()() // 调用 makeFn 函数返回的函数
// 或
const fn = makeFn()
fn()
模拟 once
函数
// once
function once (fn) {
let done = false
return function () {
if (!done) {
done = true
// 使用 apply 来调用 fn 函数, 把其中的 this 传递过来,方便改变 this
// 通过 arguments 传递 return 的 function 的参数给 fn 函数
return fn.apply(this, arguments)
}
}
}
// 声明 pay 函数 调用 once
let pay = once(function (money) {
console.log(`支付:${money} RMB`)
})
// 调用 pay 函数
// 只会支付一次
pay(5)
pay(5)
pay(5)
使用高阶函数的意义
- 抽象可以帮我们屏蔽细节,只需要关注与我们的目标
- 高阶函数是用来抽象通用的问题
- 使代码写起来更加简洁
常用高阶函数
- forEach
- map
- filter
- every
- some
- find/findIndex
- reduce
- sort
……
模拟 map()
函数
const map = (array, fn) => {
let results = []
for (let value of array) {
results.push(fn(value))
}
return results
}
let arr = [1, 2, 3, 4]
arr = map(arr, (item) => item * item)
console.log(arr)
模拟 every()
函数
const every = (array, fn) => {
let result = true
for (let value of array) {
result = fu(value)
if (!result) {
break
}
}
return result
}
let arr = [9, 12, 13]
let r = every(arr, (item) => item > 10)
console.log(r)
( js中break,return,continue区别 )
模拟 some()
函数
const some = (array, fn) {
let result = false
for (let value of array) {
result = fn(value)
if (result) {
break
}
}
return result
}
let arr = [1, 3, 4, 5]
let r = some(arr, (item) => item % 2 === 0)
console.log(r)
闭包
- 闭包 (Closure):函数和其周围的状态(词法环境)的引用捆绑在一起形成闭包。
- 可以在另一个作用域(例如函数C)中调用一个函数(函数A)的内部函数(函数B)并访问到该函数(函数A)的作用域中的成员
- 闭包的本质:函数在执行的时候会放到一个执行栈上当函数执行完毕之后会从执行栈上移除,但是
堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员
// 闭包
function fnB () {
let msg = 'Hello function'
return function () { // fnC
console.log(msg)
}
}
const fnA = fnB()
fnA()
- 闭包案例
// 生成计算数字的多少次幂的函数
function makePower (power) {
return function (number) {
return Math.pow(number, power)
}
}
// 2次方
let power2 = makePower(2)
// 3次方
let power3 = makePower(3)
console.log(power2(2))
console.log(power2(5))
console.log(power3(5))
运行以上代码,在开发者工具中打断点调试,查看函数运行过程。
Call Stack 为当前站点调用函数,可以在途中看到调用两个匿名函数
Scope 为作用域,Local 为局部作用域(里面的变量是 number,this 指向是 Window)
Closure 为闭包(里面是跟闭包相关的变量 power ),跟闭包相关的外部函数是 makePower
通过 let
定义的变量,他的作用域可以在 Script 找到,通过 var
定义的变量会挂载在 Global 全局对象上