问题: 创建一个将两个参数相加的函数。 如果只提供了一个参数,则返回一个需要一个参数并返回总和的函数。
例如,addTogether(2,3)应返回5,addTogether(2)应返回一个函数。
使用单个参数调用此返回的函数将返回总和: var sumTwoAnd = addTogether(2); sumTwoAnd(3)返回5.
如果任一参数不是有效数字,则返回undefined。
解决方案应该返回:
addTogether(2,3)应该返回5。 addTogether(2)(3)应该返回5。 addTogether(2,“3”)应返回undefined。 addTogether(2)([3])应返回undefined。
我尽我所能,但唯一有用的,据称是迄今为止最好的解决方案如下:
function addTogether() {
"use strict";
// check if argument(s) valid number
var validateNum = function(num) {
if(typeof num !== 'number') {
return undefined;
} else
return num;
};
// is there is one argument or two
if(arguments.length > 1) {
var a = validateNum(arguments[0]);
var b = validateNum(arguments[1]);
if(a === undefined || b === undefined) {
return undefined;
} else {
return a + b;
}
// if only one argument, return function that expects one argument and returns sum.
} else {
var c = arguments[0];
// start here
if(validateNum(c)) {
return function(arg2) {
if(c === undefined || validateNum(arg2) === undefined) {
return undefined;
} else {
return c + arg2;
}
}; // belongs to return function(arg2) {}
}
}
}
addTogether(2)(3);
答案 0 :(得分:1)
function addTogether(a, b) {
if (typeof a == "number") {
if (arguments.length == 1) {
return b => addTogether(a, b);
} else if (typeof b == "number") {
return a + b;
}
}
}
// as per OP's code
// returns 3
console.log("addTogether(1, 2) = " + addTogether(1, 2));
console.log("addTogether(1, 2, 3) = " + addTogether(1, 2, 3));
console.log("addTogether(1)(2) = " + addTogether(1)(2));
console.log("addTogether(1)(2, 3) = " + addTogether(1)(2, 3));
console.log("addTogether(1, 2, '3') = " + addTogether(1, 2, '3'));
console.log("addTogether(1)(2, '3') = " + addTogether(1)(2, '3'));
console.log("addTogether(1, 2, [3]) = " + addTogether(1, 2, [3]));
console.log("addTogether(1)(2, [3]) = " + addTogether(1)(2, [3]));
console.log("addTogether(1, 2, NaN) = " + addTogether(1, 2, NaN));
console.log("addTogether(1)(2, NaN) = " + addTogether(1)(2, NaN));
// returns NaN
console.log("addTogether(1, NaN) = " + addTogether(1, NaN));
console.log("addTogether(1)(NaN) = " + addTogether(1)(NaN));
// returns undefined
console.log("addTogether() = " + addTogether());
console.log("addTogether(1)() = " + addTogether(1)());
console.log("addTogether('1') = " + addTogether('1'));
console.log("addTogether(1, '2') = " + addTogether(1, '2'));
console.log("addTogether(1)('2') = " + addTogether(1)('2'));
console.log("addTogether(1, [2]) = " + addTogether(1, [2]));
console.log("addTogether(1)([2]) = " + addTogether(1)([2]));
已经提出了以下改进,但它们会改变OP代码的语义:
undefined
或a
为b
则返回NaN
,因为NaN
不是“有效号码”undefined
如果提供的参数超过两个而不是静默删除它们(感谢@PatrickRoberts)如果您不介意为e返回功能。 G。 addTogether('x')
,使用:
function addTogether(a, b) {
if (arguments.length == 1) {
return b => addTogether(a, b);
} else if (typeof a == "number" && typeof b == "number") {
return a + b;
}
}
这样,您将始终为一个参数返回function
,并为两个或多个参数返回Number
或undefined
=更健壮的代码。
要获得ES5兼容性,如果您不介意addTogether(2)()
返回某个功能,请将b => addTogether(a, b)
替换为addTogether.bind(undefined, a)
(感谢@PatrickRoberts)。
答案 1 :(得分:1)
您可以使用点差运算符来改善您的功能以及Array
或some
等一些reduce
函数:
这样addTogether
可以接受多个参数。
如果使用一个参数调用addTogether
,则返回的函数也可以使用多个参数调用。
let isNotNumber = number=> typeof number != 'number';
let addTogether = function(...numbers){
if(!numbers.length) return;
if(numbers.length == 1){
if(isNotNumber(numbers[0])) return;
return function(...otherNumbers){
if(otherNumbers.some(isNotNumber)) return;
return otherNumbers.reduce((prev, curr)=> prev + curr, numbers[0]);
}
} else {
if(numbers.some(isNotNumber)) return;
return numbers.reduce((prev, curr)=> prev + curr);
}
}
// Will return a value
console.log(addTogether(1,2,3));
console.log(addTogether(1)(2,3));
// Will return undefined
console.log(addTogether(1, [2]));
console.log(addTogether(1)('2'));
console.log(addTogether(1)([2]));
console.log(addTogether());

答案 2 :(得分:1)
根据jscomplexity.org,OP的函数的圈复杂度为8,而下面的解决方案的圈复杂度为5(based on the Babel ES5 transpilation)。
此解决方案在功能上等同于OP的代码,请参阅以下测试:
'use strict';
function addTogether(...augends) {
if (augends.slice(0, 2).every(value => typeof value === 'number')) {
switch (augends.length) {
case 0:
return;
case 1:
return (addend) => addTogether(augends[0], addend);
default:
return augends[0] + augends[1];
}
}
}
// should work (returns 3)
console.log("addTogether(1, 2) = " + addTogether(1, 2));
console.log("addTogether(1, 2, 3) = " + addTogether(1, 2, 3));
console.log("addTogether(1)(2) = " + addTogether(1)(2));
console.log("addTogether(1)(2, 3) = " + addTogether(1)(2, 3));
console.log("addTogether(1, 2, '3') = " + addTogether(1, 2, '3'));
console.log("addTogether(1)(2, '3') = " + addTogether(1)(2, '3'));
console.log("addTogether(1, 2, [3]) = " + addTogether(1, 2, [3]));
console.log("addTogether(1)(2, [3]) = " + addTogether(1)(2, [3]));
console.log("addTogether(1, 2, NaN) = " + addTogether(1, 2, NaN));
console.log("addTogether(1)(2, NaN) = " + addTogether(1)(2, NaN));
// should return NaN (not sure if this "works" or not)
console.log("addTogether(1, NaN) = " + addTogether(1, NaN));
console.log("addTogether(1)(NaN) = " + addTogether(1)(NaN));
// should not work (returns undefined)
console.log("addTogether() = " + addTogether());
console.log("addTogether(1)() = " + addTogether(1)());
console.log("addTogether('1') = " + addTogether('1'));
console.log("addTogether(1, '2') = " + addTogether(1, '2'));
console.log("addTogether(1)('2') = " + addTogether(1)('2'));
console.log("addTogether(1, [2]) = " + addTogether(1, [2]));
console.log("addTogether(1)([2]) = " + addTogether(1)([2]));

作为参考,这是我的另一个解决方案,它禁止无关的参数,也测试文字NaN
值(具有讽刺意味的是typeof "number"
)。 修改不幸的是,由于修复了测试用例console.log("addTogether(1)() = " + addTogether(1)());
的实现,现在它的圈复杂度为7:
'use strict';
function addTogether(...augends) {
if (augends.every(value => typeof value === 'number' && !isNaN(value))) {
switch (augends.length) {
case 1:
return (addend, ...addends) => addTogether(augends[0], addend, ...addends);
case 2:
return augends[0] + augends[1];
}
}
}
// should work (returns 3)
console.log("addTogether(1, 2) = " + addTogether(1, 2));
console.log("addTogether(1)(2) = " + addTogether(1)(2));
// should not work (returns undefined)
console.log("addTogether() = " + addTogether());
console.log("addTogether(1)() = " + addTogether(1)());
console.log("addTogether('1') = " + addTogether('1'));
console.log("addTogether(1, 2, 3) = " + addTogether(1, 2, 3));
console.log("addTogether(1, '2') = " + addTogether(1, '2'));
console.log("addTogether(1)('2') = " + addTogether(1)('2'));
console.log("addTogether(1, [2]) = " + addTogether(1, [2]));
console.log("addTogether(1)([2]) = " + addTogether(1)([2]));
console.log("addTogether(1)(2, 3) = " + addTogether(1)(2, 3));
console.log("addTogether(1, 2, '3') = " + addTogether(1, 2, '3'));
console.log("addTogether(1)(2, '3') = " + addTogether(1)(2, '3'));
console.log("addTogether(1, 2, [3]) = " + addTogether(1, 2, [3]));
console.log("addTogether(1)(2, [3]) = " + addTogether(1)(2, [3]));
console.log("addTogether(1, 2, NaN) = " + addTogether(1, 2, NaN));
console.log("addTogether(1)(2, NaN) = " + addTogether(1)(2, NaN));
console.log("addTogether(1, NaN) = " + addTogether(1, NaN));
console.log("addTogether(1)(NaN) = " + addTogether(1)(NaN));

答案 3 :(得分:0)
为什么你不提供功能参数。我认为这是最简单的vay:
$(document).ready(function() {
var playing = false;
$('.audio-button').click(function() {
$(this).toggleClass("playing");
var song = $(this).find('audio').attr('src');
var audio = new Audio(song);
if (playing == false) {
audio.play();
playing = true;
} else {
audio.pause();
playing = false;
}
});
});
答案 4 :(得分:0)
我想你可以这样做。如果只提供了1个参数,它将返回当前函数,但绑定第一个参数,这样你只需要提供额外的参数
'use strict';
function isNumeric(arg) {
return typeof arg === 'number' && !isNaN(arg);
}
function sum(a, b) {
if (arguments.length > 2) {
return undefined;
}
if (isNumeric(a) && isNumeric(b)) {
return a + b;
}
if (typeof b === 'undefined' && arguments.length === 1) {
if (typeof a === 'undefined') {
return undefined;
} else if (isNumeric(a)) {
return sum.bind(this, a); // returns the sum function with the a argument bound to the current a argument
}
}
return undefined;
}
function test() {
var args = '',
result = sum,
value;
Array.prototype.forEach.call(arguments, function(argument) {
value = argument;
if (!argument) {
argument = 'undefined';
}
args += '(';
if (Array.isArray(argument)) {
args += Array.prototype.join.call(argument, ', ');
} else {
args += argument.toString();
}
args += '}';
if (typeof result === 'function') {
if (Array.isArray(value)) {
result = result.apply({}, value);
} else {
result = result.call({}, value);
}
}
});
console.log(`sum${args} = ${result}`);
}
test(2);
test([2, 3]);
test(2, 3);
test([2, undefined], 3);
test([2, "3"]);
test(2, [
[3]
]);
test(2, "3");
test(2, [3]);
test([NaN, 2]);

答案 5 :(得分:0)
您应该阅读有关函数currying,bind,call和apply的内容。 Currying适用于ES6,但绑定,调用和应用运行无处不在。
MDN网站的详细信息 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
简而言之,您正在寻找的解决方案是:
function addTogether(a,b) {
return a+b;
}
console.log(typeof addTogether); //-->function
console.log(typeof addTogether.bind(null,2)); //-->function
console.log(addTogether.bind(null,2)(3));//5
console.log(addTogether(2,3)); //-->5
是的,这很简单,不是开玩笑!
答案 6 :(得分:0)
这还不算短,但是我克服了挑战,很高兴避免分享我的解决方案:
function addTogether(...args) {
if (args.length == 0) {
//there is no args provided to the function .. lets return undefined
return undefined;
} else {
//so there are arguments provided to the function
if (args.length >= 2) {
//there are two or more arguments provided to the function, lets consider only the first two arguments
if (typeof(args[0]) != "number" || typeof(args[1]) != "number") {
//so at least one of the first two arguments is not a number, lets return undefined
return undefined;
} else {
//so both of the first two arguments are numbers, lets return their sum
return args[0] + args[1];
}
} else { //handling input of one argument
if (typeof(args[0]) != "number") {
//the only argument provided is not even a number, lets return undefined
return undefined;
} else {
//lets return a function that will wait for another argument 'y' to be summed with the currently provided argument 'args[0]'
return function(y) {
//first lets check if the second argument newly provided is a number or not
if (typeof(y) != "number") return undefined;
else return args[0] + y;
};
}
}
}
}
console.log(addTogether(2, 3)); // should return 5.
console.log(addTogether(2)(3)); // should return 5.
console.log(addTogether(2, "3")); // should return undefined.
console.log(addTogether(2)([3])); // should return undefined.