> addOne(1, 2, 3)
TypeError: arguments.map is not a function
at test (repl:2:18)
at repl:1:1
at ContextifyScript.Script.runInThisContext (vm.js:44:33)
at REPLServer.defaultEval (repl.js:239:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:440:10)
at emitOne (events.js:120:20)
at REPLServer.emit (events.js:210:7)
at REPLServer.Interface._onLine (readline.js:279:10)
这是因为arguments 实际上不是数组,而是类似数组的对象。 可以使用slice实现此功能,如下所示:
function addOne() { return Array.prototype.slice.call(arguments).map(i => i+1) }
现在就可以得到了你所希望的数据:
> addOne(1, 2, 3) [ 2, 3, 4 ]
用法7:将任意长度多余的参数强制转换为数组
有时希望接受函数的多余参数,组成一个数组。
较新版本的JavaScript引入了所谓的Rest语法来处理这个问题,但是如果为为了兼容旧浏览器,你可以使用slice做到这一点:
function myFunc(a, b) { const extraArgs = Array.prototype.slice.call(arguments, 2); }
这允许使用任意数量的参数调用myFunc, 例如:
myFunc(1, 2, 3, 4, 5, 6, 7, 8)
在函数里面会得到a == 1,b === 2,extraArgs=== [3,4,5,6,7,8]
用法8:修改数组中的特定索引
slice在函数上下文中一个强大而常见的用法是替换数组中特定项的值。
从本质上讲,这很简单,只需要分配新值,但是在函数世界中,不能修改原始数组。
相反,可以将slice与扩展运算符一起使用,以返回一个相同但对于要更新的索引的新数组:
function replaceIdx(arr, index, newVal) { return [ ...arr.slice(0, index), newVal, ...arr.slice(index + 1) ] }
偏函数应用
偏函数应用,英文是partial application,也可以译作“局部应用”、“部分应用”、“偏应用”
函数式编程中的另一种常见模式是所谓的偏函数应用:将函数预先应用于函数,然后返回一个新函数。
这种模式允许你组合函数,通过使用具有不同预应用参数的相同核心函数来创建更大的可重用性。
虽然像Haskell这样的纯函数语言本身支持偏函数应用程序,但是在JavaScript中,我们可以使用slice实现一个函数来实现它
var partial = function() { const fn = arguments[0]; const args = Array.prototype.slice.call(arguments, 1); // Return a function that calls fn return function() { var remainingArgs = Array.prototype.slice.call(arguments); return fn.apply(this, args.concat(remainingArgs)); } }