js函数柯里化的理解
Posted vcxiaohan2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js函数柯里化的理解相关的知识,希望对你有一定的参考价值。
函数柯里化理解示例
// 求和
let add = function (a, b, c)
return a + b + c
/* 简单版curry函数示例 */
// 对求和函数做curry化
let f1 = curry(add, 1, 2, 3)
console.log('简单版', f1())// 6
// 对求和函数做curry化
let f2 = curry(add, 1, 2)
console.log('简单版', f2(3))// 6
// 对求和函数做curry化
let f3 = curry(add)
console.log('简单版', f3(1, 2, 3))// 6
// 但是简单版curry函数多次调用会报错,如下:
// console.log('简单版',f3(1)(2)(3))// Uncaught TypeError: f3(...) is not a function
// 简单版(只能调用1次)
function curry(fn)
// 缓存除函数fn之外的所有参数
let args = Array.prototype.slice.call(arguments, 1)
// 闭包
return function ()
// 连接已缓存的老的参数和新传入的参数(即把每次传入的参数全部先保存下来,但是并不执行)
let newArgs = args.concat(Array.from(arguments))
// 调用,这里的apply只是为了方便传参数,可以不用
return fn.apply(null, newArgs)
/* 复杂版curry函数示例 */
// 对求和函数做curry化
let f1 = curry(add, 1, 2, 3)
console.log('复杂版', f1())// 6
// 对求和函数做curry化
let f2 = curry(add, 1, 2)
console.log('复杂版', f2(3))// 6
// 对求和函数做curry化
let f3 = curry(add)
console.log('复杂版', f3(1, 2, 3))// 6
// 复杂版curry函数可以多次调用,如下:
console.log('复杂版', f3(1)(2)(3))// 6
console.log('复杂版', f3(1, 2)(3))// 6
console.log('复杂版', f3(1)(2, 3))// 6
// 复杂版(每次可传入不定数量的参数,当所传参数总数不少于函数的形参总数时,才会执行)
function curry(fn)
// 闭包
// 缓存除函数fn之外的所有参数
let args = Array.prototype.slice.call(arguments, 1)
return function ()
// 连接已缓存的老的参数和新传入的参数(即把每次传入的参数全部先保存下来,但是并不执行)
let newArgs = args.concat(Array.from(arguments))
if (newArgs.length < fn.length) // 累积的参数总数少于fn形参总数
// 递归传入fn和已累积的参数,这里的call只是为了方便传参数,可以不用
return curry.call(null, fn, ...newArgs)
else
// 调用,这里的apply只是为了方便传参数,可以不用
return fn.apply(null, newArgs)
参数解构版本:
function curry(fn, ...args)
return function(...newArgs)
let allArgs = args.concat(newArgs)
if(allArgs.length<fn.length)
return curry(fn, ...allArgs)
else
return fn(...allArgs)
js bind函数理解示例(使用了柯里化)
// 全局变量
a = 1
// 求和
let add = function (b, c)
return this.a + b + c
/* 作为普通函数直接调用 */
// 此时this指向window,window.a是1
console.log(add(2, 3))// 6
/* 简单版bind实现,不具备curry化效果(不支持在传入对象的同时传入其他参数) */
Function.prototype.bind = function (obj)
// 缓存Function构造函数的this(表达式函数声明时相当于new Function...)
const self = this
// 闭包
return function ()
// 调用
return self.apply(obj, arguments)
let f1 = add.bind( a: 0 )
console.log(f1(2, 3))// 5
// 但是简单版bind实现不支持对象和其他参数同时传入,如下:
let f2 = add.bind( a: 0 , 2, 3)
// 因为上一行代码传入的2、3并没有接收到,所以求和后返回NaN
console.log(f2())// NaN
/* 复杂版bind实现,具备部分curry化效果(之所以说部分,是因为它支持在传入对象的同时可以其他参数,但是不支持多次调用) */
Function.prototype.bind = function (obj)
// 缓存Function构造函数的this(表达式函数声明时相当于new Function...)
const self = this
// 缓存除函数fn之外的所有参数
let args = Array.prototype.slice.call(arguments, 1)
// 闭包
return function ()
// 连接已缓存的老的参数和新传入的参数(即把每次传入的参数全部先保存下来,但是并不执行)
let newArgs = args.concat(Array.from(arguments))
// 调用
return self.apply(obj, newArgs)
let f1 = add.bind( a: 0 )
console.log(f1(2, 3))// 5
// 复杂版bind实现支持对象和其他参数同时传入,如下:
let f2 = add.bind( a: 0 , 2, 3)
console.log(f2())// 5
// 但是复杂版bind实现多次调用会报错,如下:
let f3 = add.bind( a: 0 )
// console.log(f3(2)(3))// Uncaught TypeError: f3(...) is not a function
装饰者模式理解示例(使用了柯里化)
大家看以下代码,是不是思路都是想通的,详细的大家就自行拓展吧
// 在之前执行
Function.prototype.before = function (fn)
let self = this
return function ()
fn.apply(this, arguments)
return self.apply(this, arguments)
// 在之后执行
Function.prototype.after = function (fn)
let self = this
return function ()
let res = self.apply(this, arguments)
fn.apply(this, arguments)
return res
function foo(params)
console.log(params, 1)
return 22
// 钩子可以共享参数和返回值
console.log(foo.before((params) =>
console.log(params, 2)
).after((params) =>
console.log(params, 3)
)( a: 1 ))
以上是关于js函数柯里化的理解的主要内容,如果未能解决你的问题,请参考以下文章