Javascript 函数挑战 add(1,2) 和 add(1)(2) 都应该 return 3
Javascript function challenge add(1,2) and add(1)(2) both should return 3
我的一个朋友向我提出挑战,要求我编写一个适用于这两种情况的函数
add(2,4) // 6
add(2)(4) // 6
我的直觉是编写一个 return 本身的 add() 函数,但我不确定我的方向是否正确。这失败了。
function add(num1, num2){
if (num1 && num2){
return num1 + num2;
} else {
return this;
}
}
alert(add(1)(2));
所以我开始阅读 return 其他函数或 return 本身的函数。
- http://davidwalsh.name/javascript-functions
- JavaScript: self-calling function returns a closure. What is it for?
- JavaScript: self-calling function returns a closure. What is it for?
我会继续尝试,但如果有人有巧妙的解决方案,我很乐意看到它!
function add(num1, num2){
if (num1 && num2) {
return num1 + num2;
} else if (num1) {
return function(num2){return num1 + num2;};
}
return 0;
}
我写了一个curried function whose valueOf()
method and function context (this
)不管每次传入多少个参数都绑定sum
/* add function */
let add = function add(...args) {
const sum = args.reduce((acc, val) => acc + val, this);
const chain = add.bind(sum);
chain.valueOf = () => sum;
return chain;
}.bind(0);
/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
let add7 = add(7);
console.log('let add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));
之所以需要这两种机制是因为 add()
的主体必须使用被调用函数的绑定上下文才能访问中间 partial application 的总和,并且调用站点必须使用valueOf()
成员(隐式或显式)以访问最终总和。
您正在寻找的概念称为 currying,它与函数转换和部分函数应用有关。当您发现自己使用几乎相同的参数一遍又一遍地调用相同的函数时,这很有用。
通过柯里化实现 add(2)(6)
的示例如下所示...
function add(x,y) {
if (typeof y === 'undefined') {
return function(y) {
return x + y;
}
}
}
add(2)(4); // => 6
另外,你可以做这样的事情...
var add6 = add(6);
typeof add6; // => 'function'
add6(4); // => 10
var add = function(){
// the function was called with 2 arguments
if(arguments.length > 1)
arguments.callee.first_argument = arguments[0];
// if the first argument was initialized
if(arguments.callee.first_argument){
var result = arguments.callee.first_argument + arguments[arguments.length - 1];
arguments.callee.first_argument = 0;
return result;
}else{// if the function was called with one argument only then we need to memorize it and return the same function handler
arguments.callee.first_argument = arguments.callee.first_argument || arguments[0];
return arguments.callee;
}
}
console.log(add(2)(4));
console.log(add(2, 4));
依赖于环境的扩展方案:
function add(){
add.toString = function(){
var answer = 0;
for(i = 0; i < add.params.length; i++)
answer += add.params[i];
return answer;
};
add.params = add.params || [];
for(var i = 0; i < arguments.length; i++)
add.params.push(arguments[i])
return add;
}
console.log(add(2)(4)(6)(8))
console.log(add(2, 4, 6, 8));
Dr.Dobs 期刊上有一篇关于“Currying and Partial Functions in JavaScript”的文章正是描述了这个问题。
本文中找到的一个解决方案是:
// a curried add
// accepts partial list of arguments
function add(x, y) {
if (typeof y === "undefined") { // partial
return function (y) {
return x + y;
};
}
// full application
return x + y;
}
我们可以使用Javascript提供的闭包概念。
代码片段:
function add(a,b){
if(b !== undefined){
console.log(a + b);
return;
}
return function(b){
console.log(a + b);
}
}
add(2,3);
add(2)(3);
可能有人认为he/she必须调用同一个函数两次,但如果你深入思考你会发现问题很简单,你必须调用一次add函数然后你需要调用添加函数 returns.
function add(a){
return function(b){
return a+b;
}
}
console.log(add(20)(20));
//output: 40
您可以 return 想玩多少次就玩多少次。假设 y = mx+c
const y= function (m){
return function(x){
return function (c){
return m*x+c
}
}
}
console.log(y(10)(5)(10));
//out put: 60
一般来说,您需要就函数应该 return 一个函数(用于调用更多参数)还是最终结果达成一致。想象一下 add
函数也必须像这样工作:
add(1, 2, 3)(4, 5) // -> 15
...然后它变得模棱两可,因为你可能想再次调用:
add(1, 2, 3)(4, 5)(6) // -> 21
...所以 add(1, 2, 3)(4, 5)
应该 returned 一个函数,而不是 15.
例如,您可以同意必须再次调用函数 ,但不带参数,以便获得数字结果:
function add(...args) {
if (args.length === 0) return 0;
let sum = args.reduce((a, b) => a+b, 0);
return (...args) => args.length ? add(sum, ...args) : sum;
}
console.log(add()); // 0
console.log(add(1,2,3)()); // 6
console.log(add(1,2,3)(4,5)()); // 15
console.log(add(1,2,3)(4,5)(6)()); // 21
我的一个朋友向我提出挑战,要求我编写一个适用于这两种情况的函数
add(2,4) // 6
add(2)(4) // 6
我的直觉是编写一个 return 本身的 add() 函数,但我不确定我的方向是否正确。这失败了。
function add(num1, num2){
if (num1 && num2){
return num1 + num2;
} else {
return this;
}
}
alert(add(1)(2));
所以我开始阅读 return 其他函数或 return 本身的函数。
- http://davidwalsh.name/javascript-functions
- JavaScript: self-calling function returns a closure. What is it for?
- JavaScript: self-calling function returns a closure. What is it for?
我会继续尝试,但如果有人有巧妙的解决方案,我很乐意看到它!
function add(num1, num2){
if (num1 && num2) {
return num1 + num2;
} else if (num1) {
return function(num2){return num1 + num2;};
}
return 0;
}
我写了一个curried function whose valueOf()
method and function context (this
)不管每次传入多少个参数都绑定sum
/* add function */
let add = function add(...args) {
const sum = args.reduce((acc, val) => acc + val, this);
const chain = add.bind(sum);
chain.valueOf = () => sum;
return chain;
}.bind(0);
/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
let add7 = add(7);
console.log('let add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));
之所以需要这两种机制是因为 add()
的主体必须使用被调用函数的绑定上下文才能访问中间 partial application 的总和,并且调用站点必须使用valueOf()
成员(隐式或显式)以访问最终总和。
您正在寻找的概念称为 currying,它与函数转换和部分函数应用有关。当您发现自己使用几乎相同的参数一遍又一遍地调用相同的函数时,这很有用。
通过柯里化实现 add(2)(6)
的示例如下所示...
function add(x,y) {
if (typeof y === 'undefined') {
return function(y) {
return x + y;
}
}
}
add(2)(4); // => 6
另外,你可以做这样的事情...
var add6 = add(6);
typeof add6; // => 'function'
add6(4); // => 10
var add = function(){
// the function was called with 2 arguments
if(arguments.length > 1)
arguments.callee.first_argument = arguments[0];
// if the first argument was initialized
if(arguments.callee.first_argument){
var result = arguments.callee.first_argument + arguments[arguments.length - 1];
arguments.callee.first_argument = 0;
return result;
}else{// if the function was called with one argument only then we need to memorize it and return the same function handler
arguments.callee.first_argument = arguments.callee.first_argument || arguments[0];
return arguments.callee;
}
}
console.log(add(2)(4));
console.log(add(2, 4));
依赖于环境的扩展方案:
function add(){
add.toString = function(){
var answer = 0;
for(i = 0; i < add.params.length; i++)
answer += add.params[i];
return answer;
};
add.params = add.params || [];
for(var i = 0; i < arguments.length; i++)
add.params.push(arguments[i])
return add;
}
console.log(add(2)(4)(6)(8))
console.log(add(2, 4, 6, 8));
Dr.Dobs 期刊上有一篇关于“Currying and Partial Functions in JavaScript”的文章正是描述了这个问题。
本文中找到的一个解决方案是:
// a curried add
// accepts partial list of arguments
function add(x, y) {
if (typeof y === "undefined") { // partial
return function (y) {
return x + y;
};
}
// full application
return x + y;
}
我们可以使用Javascript提供的闭包概念。
代码片段:
function add(a,b){
if(b !== undefined){
console.log(a + b);
return;
}
return function(b){
console.log(a + b);
}
}
add(2,3);
add(2)(3);
可能有人认为he/she必须调用同一个函数两次,但如果你深入思考你会发现问题很简单,你必须调用一次add函数然后你需要调用添加函数 returns.
function add(a){
return function(b){
return a+b;
}
}
console.log(add(20)(20));
//output: 40
您可以 return 想玩多少次就玩多少次。假设 y = mx+c
const y= function (m){
return function(x){
return function (c){
return m*x+c
}
}
}
console.log(y(10)(5)(10));
//out put: 60
一般来说,您需要就函数应该 return 一个函数(用于调用更多参数)还是最终结果达成一致。想象一下 add
函数也必须像这样工作:
add(1, 2, 3)(4, 5) // -> 15
...然后它变得模棱两可,因为你可能想再次调用:
add(1, 2, 3)(4, 5)(6) // -> 21
...所以 add(1, 2, 3)(4, 5)
应该 returned 一个函数,而不是 15.
例如,您可以同意必须再次调用函数 ,但不带参数,以便获得数字结果:
function add(...args) {
if (args.length === 0) return 0;
let sum = args.reduce((a, b) => a+b, 0);
return (...args) => args.length ? add(sum, ...args) : sum;
}
console.log(add()); // 0
console.log(add(1,2,3)()); // 6
console.log(add(1,2,3)(4,5)()); // 15
console.log(add(1,2,3)(4,5)(6)()); // 21