关于arguments对象以及函数的柯里化;
1、arguments对象
Arguments是个类似数组但不是数组的对象,说他类似数组是因为其具备数组相同的访问性质及方式,能够由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length。还有就是arguments对象存储的是实际 传递给函数的参数,而不局限于函数声明所定义的参数列表,而且不能显式创建 arguments 对象。在JavaScript中函数不介意传递进来多少参数,也不会因为参数不统一而错误。实际上,函数体内可以通过 arguments 对象来接收传递进来的参数。
function box() { return arguments.length; //得到 6 } alert(box(1, 2, 3, 4, 5, 6));
我们可以利用 length 这个属性, 来智能的判断有多少参数, 然后把参数进行合理的应用。 比如,要实现一个加法运算,将所有传进来的数字累加,而数字的个数又不确定。
function sum() { var sum = 0; if (arguments.length == 0) return sum; //如果没有参数,退出 for (var i = 0; i < arguments.length; i++) { sum += arguments[i] } return sum; } console.log(sum(1, 3, 5)) // 9
arguments对象中有一个非常有用的属性:callee。arguments.callee返回此arguments对象所在的当前函数引用。在使用函数递归调用时推荐使用arguments.callee代替函数名本身。
function count(a) { if (a == 0) return 1; return a + arguments.callee(--a); } var s = count(5) console.log(s); // 16 == >5+4+3+2+1+1
2、柯里化
在javascript中,函数可以接受多个参数,并且这些参数可以不固定(arguments),而柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
通用实现:
function currying(fn) { if (typeof fn !== 'function') throw new Error("currying():fn must be function"); var args = [].slice.call(arguments, 1) return function() { var newArgs = args.concat([].slice.call(arguments)) return fn.apply(null, newArgs) } }
来看一个例子:
function currying(fn) { //var args = Array.prototype.slice.call(arguments,1) if (typeof fn !== 'function') throw new Error("currying():fn must be function"); var args = [].slice.call(arguments, 1); return function() { var newArgs = args.concat([].slice.call(arguments)); return fn.apply(null, newArgs); } } var getPerson = currying(function() { var args = [].slice.call(arguments); console.log(args.toString()); }, "jone") getPerson('jack', "tome", "eric") // jone,jack,tome,eric getPerson('张三') // jone,张三
思考题:已知fn为一个预定义函数,实现函数curryIt
var fn = function(a, b, c) { return a + b + c }; curryIt(fn)(1)(2)(3); //6 function curryIt(fn) { //这里补充 }
可以试着玩一下,这里是用的函数的柯里化
function curryIt(fn) { if (typeof fn !== 'function') throw new Error("curryIt():fn must be function"); var args = [].slice.call(arguments, 1) return function() { args = args.concat([].slice.call(arguments)); if (args.length < fn.length) { return arguments.callee; } else { return fn.apply(null, args) } } }
参考: