谈谈闭包,柯里化,以及偏函数的关系
一.闭包
闭包是一个引用该函数作用于外的某个变量的一个函数和这个外部变量的总和。简单地说就是 一个函数,引用了其作用于外的变量,那么这个函数和这个变量就组成了一个闭包。
闭包的写法
//闭包
function Person() {
var name = ''
var age = 10
var gender = 'male'
this.setAge = function (arg) {
age = arg
}
this.getAge = function () {
return age
}
}
const person = new Person()
person.setAge(30)
console.log(person.getAge())
console.log(person.age) // 30
针对 Person 这个构造函数,内部有 name , age 和 gender 三个“私有变量”,这三个变量的作用域仅仅在 Person构造函数下,外部访问不到。 这三个变量与 setAge 和 getAge 组成了闭包。
这样一来的好处就是我们无法直接通过 Person的对象直接访问到这三个变量,也无法修改。 仅仅通过其内部方法获得或修改。这也是闭包的常见用途,即变量的私有化。
二. 科里化函数
百度定义:柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
简单地说就是将原本接收多个参数的函数转换成仅接收一个参数的函数,并且返回一个新的函数。代码意义就是:
f(a,b,c)转化为f(a)(b)(c)
这个转换过程,我们称之为函数的科里化。
实现函数的科里化
//Person(name, age, gender)
function Person(name) {
return function (age) {
return function (gender) {
console.log(name, age, gender)
}
}
}
Person('ouda')(18)('male') // ouda 18 male
这里利用了闭包,将原先可能 Person(name, age, gender) 的调用方式改为了 Person('ouda')(18)('male') 的调用方式。可以发现函数的科里化本质是接收但个参数,返回一个函数,内部采用函数的嵌套(或递归)去实现的。函数的科里化是闭包的应用场景之一。
三 偏应用函数
偏应用函数指使用一个函数并将其应用一个或多个参数,但不是全部参数,在这个过程中创建一个新函数,这个函数用于接受剩余的参数。
实现偏应用函数
// 偏应用函数
function Person() {
}
var setPersonAgeAndGender = function (person, age, gender) {
person.age = age
person.gender = gender
return person
}
var createPerson = function (fn, name) {
const person = new Person()
person.name = name
return function (age, gender) {
return fn(person, age, gender)
}
}
var createPersonFunction = createPerson(setPersonAgeAndGender, 'ouda')
const person = createPersonFunction(18, 'male')
console.log(person) //Person { name: 'ouda', age: 18, gender: 'male' }
结合以上代码来理解偏应用函数的定义。发现我们先将 person 的 name 参数固定,然后返回一个函数,这个函数用来接收 age 和 gender 。这个就是偏应用函数的实现过程。
总结:
首先函数的科里化和偏应用函数都是通过闭包去实现的。比较容易弄混淆的是科里化和偏函数之间的差异,总的来说他们都是返回一个函数,但是返回函数的初衷不同,最主要的理解在于一句话: 科里化返回的函数是为了接收下一个参数,偏应用函数返回的函数是为了接收剩下的参数。