让我们假设我们正在调用一个需要两个参数的函数,但是它只能与一个参数一起使用,因为第二个参数是可选的,而我们使用的函数具有一个带有多个参数的回调:
['1','2','3'].map(parseInt);
在这种情况下,输出将为NaN, NaN, 3
,因为映射回调具有多个参数(value
,index
和原始的array
),并且parseInt期望有两个自变量(number
和base
),但只能使用一个参数。因此,要解决此问题并获得预期的输出,我们可以使用类似以下代码的显式回调:
['1','2','3'].map((value) => parseInt(value));
还有另一种方法可以不使用显式的回调吗?如果不是,函数语言将如何实现?
答案 0 :(得分:3)
不幸的是……不,您必须使用一种称为适配器的功能(基本上是将某物的输入更改为另一物的功能,例如RGB到HDMI),并且您在此使用的特定适配器经常称为unary
适配器(仅接受1个参数)。当然,您还可以使用其他* ary(一元,二进制,ary)适配器,但是通过功能语言,您基本上可以使用适配器来在需要时使用闭包来更改函数的占用空间:
function unary(fn){
return function(a){
return fn(a)
}
}
['1','2','3'].map(unary(parseInt))
现在,这并不是说这是解决此问题的唯一方法。您也可以将其传递给Number:
['1','2','3'].map(Number)
或者,如果您想变得有点奇怪,请使用速记parseint
通话(+
)
['1','2','3'].map(v => +v) // using an arrow function for brevity
但是到那时,您仅为parseint
编写了一个详细的一次性适配器。
答案 1 :(得分:0)
.map
会显示在中缀位置。这对于面向对象的样式很常见,在这种样式中,方法动态绑定到调用它们的对象。编写功能更强的程序,可能首先从具有更功能性接口的map
函数开始。
const map = (f, xs) =>
xs .map (x => f (x))
console.log (map (Number, [ '1', '2', '3' ]))
// [ 1, 2, 3 ]
上面,我们在幕后使用了相同的Array.prototype.map
,但我们在 prefix 位置调用了map
,这是一种较为常见的功能样式。
或者,如果您愿意,我们可以从头开始编写map
const identity = x =>
x
const None =
Symbol ()
const map = (f = identity, [ x = None, ...xs ]) =>
x === None
? []
: [ f (x), ...map (f, xs) ]
console.log (map (Number, [ '1', '2', '3' ]))
// [ 1, 2, 3 ]