js的一道关于调用累加函数(参数个数可自由控制,即函数柯里化)的面试题

题:写一个关于按照下面方式调用都能正常工作的sum方法,如果可以,写出sum方法的扩展形式。

面试题示例调用代码:

console.log(sum(2,3));//output 5
console.log(sum(2)(3));//output 5

这个我拿到手之后,第一个很好实现,难的是第二个,看到第二个的时候我心里想的是这个方法最后要return一个函数,而且是一个能参数累加的函数,这又让我想起jquery的链式调用,也有点类似调用promise的感觉,因为每次调用promise都会返回一个promise对象,这也是我想到链式调用的导火线。但,怎么实现呢?

首先第一个:

function sum(x,y){
    return x + y;
}

了解过js的人都知道会这么写,那么看第二个具体怎么实现呢?首先我们要知道函数是有显式参数和隐式参数之分的,显式参数如第一个实现里的x和y,而隐式参数也就是函数的内置对象arguments,arguments对象包含了函数调用的参数数组。

第二个(包括将第一个实现):

var sum = function (){
	var cache;
	if (arguments.length === 1) {
		cache = arguments[0];//如果arguments对象的长度为1,也就是参数只有1个时,将这个参数赋值给cache,暂存
		return function (number){//返回一个函数,函数里的参数(也就是第二个括号里的参数)与之前第一个括号里的参数相加
			return cache + number
		}
	}else{
		return arguments[0] + arguments[1]//如果arguments对象的长度不为1,那么两个参数相加
	}
}
console.log(sum(2,3));//5
console.log(sum(2)(3));//5

这个实现主要要注意,sum(2)(3)的运算顺序实际上是先运算sum(2)然后再运算sum(3),实现方法是先将第一个括号里的参数2暂存,然后将2与第二个括号里的3相加并返回。

扩展:

如果我要这样实现:

console.log(sum(2,3,4,5,6,...,n));
console.log(sum(2)(3)(4)(5)(6)...(n));

那么该怎么实现呢?上面的方法不再适用了,因为arguments对象的长度不固定,是动态变化的。而我们要实现上述参数的两种形式,且实现参数累加的效果,所以我们可以分为两种情况分别实现。

function sum(...args){//这里的三个点...是扩展运算符,该运算符将一个数组,变为参数序列。
	if([...args].length==1){//判断参数个数的形式是否为1个,即第二种形式
		var cache = [...args][0];//将第一个参数的值暂存在cache中
		var add = function (y){//创建一个方法用于实现第二个条件,最后并返回这个方法
			cache += y;
			console.log(cache)
			return add; 
		}
	return add; 
	}
	else{//这里就是参数的第一种形式
		var res = 0;//这里最好先声明要输出的变量,并给其赋值,不然值定义而不赋值会输出NaN,因为js将undefined+number两个数据类型相加结果为NaN
		for(var i = 0;i<[...args].length;i++){
			res += [...args][i]; //参数累加
		}
	console.log(res)//输出最后的累加结果
	} 
} 
sum(2,3,4);//9
sum(2)(3)(4)(5);//5//9//14

 

扫盲:

 

1.函数括号中的...args的三个点表示扩展运算符,该运算符将一个数组变为参数序列,例如:

function sum(1,2,...[3,4,5],6,7){} == function sum(1,2,3,4,5,6,7){}

2.js会将undefined+number两种数据类型相加处理结果为NaN。

你可能感兴趣的:(算法)