JavaScript - Currying (局部套用)



在 JavaScript 中,局部套用是一种函数式编程技术,用于将接受多个参数的函数转换为每个函数接受单个参数的函数序列。柯里化主要用于事件处理,以避免多次将同一变量作为函数参数传递。

如何在 JavaScript 中实现局部套用?

在 JavaScript 中有两种不同的方法可以实现局部套用,如下所示。

  • 使用 closure 函数
  • 使用 bind() 方法

使用闭包进行局部套用

在 JavaScript 中,闭包是一种内部函数可以访问外部函数的变量的技术。要使用闭包技术实现局部套用,我们可以使用函数序列,每个函数都采用一个参数。

语法

用户可以按照下面的语法来实现使用闭包的柯里化。


function funcName(a) {
	 	return function (b) {
	 	 	 // 添加更多功能
	 	 	 // OR
	 	 	 return a * b;
	 	}
}
funcName(a)(b);

在上面的语法中,'funcName()' 函数接受一个参数,它包含内部函数。内部函数也接受 1 个参数,我们在内部函数的主体中使用外部函数和内部函数的参数。

语法中给出的上述函数类似于以下函数。


function funcName(a, b) {
	 	return a * b;
}
funcName(a, b);

让我们通过示例来理解柯里化。

在下面的代码中,我们创建了 mul() 函数,该函数将单个值作为参数,并返回将 'b' 作为参数的函数。内部函数还返回另一个函数,该函数将 'c' 作为参数,并返回 'a'、'b' 和 'c' 的乘法。

当我们调用 mul(2) 函数时,它返回整个内部函数,如下所示。


return function (b) {
	 	return function (c) {
	 	 	 return a * b * c;
	 	}
}

当我们调用 mul(2)(3) 函数时,


return function (c) {
return a * b * c;
}

当我们调用 mul(2)(3)(4) 时,它返回第二个内部函数的结果。

在输出中,您可以观察到该函数返回结果 24,即 3 个值的乘积。


<html>
<head>
	 	<title>JavaScript currying using using closures</title>
</head>
<body>
	 	<div id = "output"> </div>
	 	<script>
	 	 	 // 实现咖喱
	 	 	 function mul(a) {
	 	 	 	 	return function (b) {
	 	 	 	 	 	 return function (c) {
	 	 	 	 	 	 	 	return a * b * c;
	 	 	 	 	 	 }
	 	 	 	 	}
	 	 	 }
	 	 	 // 调用currying函数
	 	 	 let result = mul(2)(3)(4);
	 	 	 document.getElementById("output").innerHTML = "The result is: " + result;
</script>
</body>
</html>

输出

The result is: 24

这样,局部套用有助于使代码更加模块化和可重用,因为它使用高阶函数。每当必须传递等于函数参数的参数数量才能获得准确结果时,局部套用就很有用。例如,如果你在上面的例子中没有传递 3 个参数,它不会返回结果。

使用 bind() 方法进行局部套用

在 JavaScript 中,bind() 方法用于创建新函数并将其存储在变量中。bind() 通常用于将参数部分预置到函数的当前参数中,从而有效地允许您局部套用函数。

语法

用户可以按照下面的语法使用 bind() 方法在 JavaScript 中实现局部套用。


let multiplyByTwo = multiply.bind(null, 2);
let multiplyByTwoAndThree = multiplyByTwo.bind(null, 3);
multiplyByTwoAndThree(4); // 产出:24

在上面的语法中,'multiply' 可以是一个带有多个参数的函数。我们使用 bind() 方法逐个预置参数并实现局部套用。

在下面的代码中,multiply() 函数接受 3 个参数并返回乘法结果。'multiply.bind()'向 multiply() 函数添加一个参数,并返回更新的函数。同样,'multiplyByTwoAndThree()' 函数存储绑定了两个预定义参数的 multiply 函数。

当我们使用单个参数调用 'multiplyByTwoAndThree()' 函数时,它返回所有 3 个参数的 60 乘法。


<html>
<head>
	 	<title>JavaScript currying using bind() method</title>
</head>
<body>
	 	<div id = "output"> </div>
	 	<script>
	 	 	 // 接受三个参数的原始乘法函数
	 	 	 function multiply(x, y, z) {
	 	 	 	 	return x * y * z;
	 	 	 }
	 	 	 // 使用bind()方法通过部分应用第一个参数(2)来实现currying
	 	 	 let multiplyByTwo = multiply.bind(null, 2);

	 	 	 // 通过部分应用第二个论点(3)来进一步讨好。
	 	 	 let multiplyByTwoAndThree = multiplyByTwo.bind(null, 3);

	 	 	 // 最后用第三个参数(10)调用curried函数并输出结果
	 	 	 document.getElementById("output").innerHTML = "The result is: " + multiplyByTwoAndThree(10);
	 	</script>
</body>
</html>

输出

The result is: 60

局部套用的用例

局部套用技术在实时软件开发的许多场景中都有使用,因为它允许代码更加模块化和可重用。在这里,我们给出了一些局部套用的实时用例。

  • 局部套用可用于处理异步操作,其中函数返回 promise。
  • 它甚至有助于处理我们需要部分应用具有特定参数的函数的情况,这些参数可以表示事件的当前上下文。
  • 它允许创建高度可配置的中间件函数,这些函数可以在代码的不同部分使用。