js - 高阶一元函数 - 为什么需要它?

时间:2017-03-18 12:53:06

标签: javascript higher-order-functions currying

此处开始:以下代码段未按预期运作:

['1', '2', '3'].map(parseInt)           // [1, NaN, NaN] <- bad output

一个简单的改变可以解决它:

['1', '2', '3'].map(a => parseInt(a))   // [ 1, 2, 3 ] <- good output


但是这篇book我的阅读有不同的补救措施:

创建一个unary函数,它接受一个函数(在我们的例子中是parseInt),如果函数有n个参数,它返回一个只有一个参数的新函数。以下是这本书的用途:

const unary = (f) => {
  return f.length === 1 ? f : (args) => f(args)
}

['1', '2', '3'].map(unary(parseInt)) // [ 1, 2, 3 ] <- good output again!

我的问题是:

  1. 这个unary功能如何运作?
  2. 任何实际情况,这个功能(或至少这个想法一般)都能很好用?
  3. 非常感谢任何帮助:)

    未来读者注意:结帐currying

3 个答案:

答案 0 :(得分:3)

  

这个一元功能如何运作?

函数的length是在第一个参数之前具有默认值*的声明的非静止参数的数量。所以unary通过查看函数是否声明只接受一个参数来工作,如果是这样,则返回原始函数,如果不是,则创建一个只用一个参数调用原始函数的新函数。

此检查不可靠,我不会使用该版本的unary。许多函数根据它们获得的实际参数数量来改变它们的行为,即使它们只声明了一个。

  

任何实际情况下,这个功能(或者至少是这个概念)都会有很好的用途吗?

总是做包装器的版本(不看length)对于像parseInt一样的情况可能很方便:你想用只有X个参数调用另一个函数(1,in你的情况),无论你的回调提供了多少。

这种事情在functional programming中很常见。如果你一般都在进行函数式编程,那么可能在箭头函数的这些日子里它没什么用处。但是相当多的人以功能的方式使用JavaScript。

*是的,这很复杂。示例(需要支持ES2015 [aka“ES6”]默认参数值和其他参数的浏览器):

function a(one) { }
function b(one, two) { }
function c(one, two, ...rest) {}
function d(one, two = 42, ...rest) {}
function e(one, two = 42, three) {}
console.log(a.length); // 1
console.log(b.length); // 2
console.log(c.length); // 2
console.log(d.length); // 1
console.log(e.length); // 1

答案 1 :(得分:2)

  

这个一元功能如何运作?

函数上的length属性返回函数具有*的形式参数的数量。 unary函数检查函数是否有一个正式参数。如果是这样,它只返回原始函数。如果没有,则返回一个新函数,该函数接受一个参数,将其传递给f,然后返回结果。

  

任何实际情况下,这个功能(或者至少是这个概念)都会有很好的用途吗?

如示例所示,某些函数会根据传入的参数数量来更改其行为。经常(例如当你使用.map时),你真的只想传递一个参数,unary()有助于此。

*或者至少它已经习惯了。随着ES6的发布,它现在变得更加复杂。见T.J.克劳德详细解答。

答案 2 :(得分:1)

在此一元函数中,fn.length正在检查parseInt的参数长度, 如果parseInt仅具有一个参数,则它将照常返回该函数。但是在这种情况下 我们在parseInt中有2个参数是parseInt(value,radix),因此我们的fn.length === 1失败。 如果它有2个参数,则返回带有一个仅是值的参数的parseInt。例如parseInt(value)不是parseInt(value,radix)