2015-08-05 3 views
0

Поскольку большинство из нас знает, мы можем создать простую функцию, подобную этой.Функция вызова двух способов с несколькими аргументами

function calc(a,b){ 
    return a+b 
} 
calc(1,1); //returns 2 

Мы также можем сделать что-то вроде этого

function calc(a){ 
    return function(b){ 
     return a+b 
    } 
} 
calc(1)(1); //returns 2 

А что, если мы имели несколько аргументов?

function calc() { 
    function r(arg) { 
     var a = []; 
     for(var i = 0, l = arg.length; i < l; i++){ 
      a[i] = arg[i]; 
     } 

     return a.reduce(function(p, c) { 
      return p + c; 
     }); 

    } 
    var res = r(arguments); 
    return function() { 
     res += r(arguments); 
     return res; 
    } 
} 

Это работает для calc(1,2)(1) но это не для calc(1,2,1)

Есть ли способ объединить обе версии? Это означает, что при вызове calc(1,1) мы могли бы также назвать calc(1)(1) и оба еще вернутся бы 2.

Или calc(1,2,3)calc(1,2)(3)calc(1)(2,3) бы все вернуть 6

+0

Использование переменной длины, то это возможно. – meskobalazs

+0

Кто-то отправил [эту ссылку] (http://stackoverflow.com/a/31795868/1250301) в [еще один вопрос] (http://stackoverflow.com/questions/31795520/a-single-function-that-can- be-called-in-two-ways/31795640 # 31795640), о функциях каррирования. Это стоит прочитать. –

+0

Возможный дубликат [Javascript sum function] (http://stackoverflow.com/questions/5832891/javascript-sum-function) – Grundy

ответ

0

Так вот ближе я пришел к моей проблеме. С кодом под ним работает, если я добавить + знак перед функцией так +calc(1,2,3)+calc(1,2)(3)+calc(1)(2)(3)+calc(1,2)(1)(3,0,1) будет все работы

function calc(){ 
    var args = [].map.call(arguments, function(a) { 
     return a; 
    }); 
    var recursiveSum = function(arr) { 
     return +arr.reduce(function(a, b) { 
      return +a + (b && b.reduce ? recursiveSum(b) : +(isNaN(b) ? 0 : b)); 
     }, 0); 
    }; 
    calc.__proto__.valueOf = function() { 
     return recursiveSum(args); 
    }; 
    return calc.bind(this, args); 
} 
+0

Переопределение «prototype.valueOf» немного рискованное, а лидерство с '+' немного хакерское, но в остальном очень умное. –

+0

в вашем случае, когда вызывается как '+ calc (1,2,3)', тогда 'this' ссылается на' window' – Grundy

+0

@Grundy, если у вас есть некоторые улучшения, дайте мне знать. Это просто для веселого кода, я не использую его в производстве, очевидно. – Marcio

1

Он должен знать, сколько аргументов сделать расчет после; -)

Вы можете сделать функцию, которая превращает вещи в такую ​​функцию что-то вроде этого:

function curry(f){ 
 
    var args = []; 
 
    return addargs; 
 
    function addargs(){ 
 
    args=args.concat([].slice.call(arguments)); 
 
    return args.length<f.length? addargs.bind(this) : f.apply(this,args); 
 
    } 
 
}

Затем вы можете сделать что-то вроде этого:

var calc = curry(function(a,b,c){return a+b+c}); 
 
calc(1,2)(3); // = 6

, но вы не можете иметь его принимать переменное число аргументов и Карри те - это не знаю, когда вернуть ответ

+2

т. Е. Вы не можете вычислить (1,2) дать 3 и calc (1,2) (3) дать 6, потому что вычисление (1,2) (3) будет делать 6 (3), а 6 не является функция – imma

0

Если бы было возможно каким-то образом сделать что-то подобное. известково (бесконечные арг) (бесконечные арг) = некоторый результат

Это может быть ближе, я могу представить себе, что вы хотите:

function calc(a,b) {      // we expect a and b to be arrays 
 
    if (Array.isArray(a)) {    // check if a is an array 
 
     if (b === undefined) {   // if we don't have a b 
 
      return calc.bind(null, a); // return a curried function 
 
     } 
 
     if (!Array.isArray(b)) {   // if b isn't an array 
 
      return calc(a, [].splice.call(arguments,1)); // turn all the arguments 
 
                  // after a into an array and 
 
                  // call the function again 
 
     } 
 
     // if both a and b are arrays, just calculate the sum and return it 
 
     var aSum = a.reduce(function(p,c) { return p + c },0); 
 
     return b.reduce(function(p,c) { return p + c}, aSum); 
 
    } 
 
    // if a was not an array, turn the arguments into an array and call again 
 
    return calc([].splice.call(arguments,0)); 
 
} 
 

 
console.log(calc(1,2)(null));  // 3 
 
console.log(calc(1,2)(3,4));  // 10 
 
console.log(calc(1)(3,4));   // 8 
 
console.log(calc(1,2,3)(null)); // 6

Ограничением здесь является то, что может 't do calc(1,2), потому что он возвращает функцию, поэтому, если вы хотите получить результат, единственный способ сделать это - позвонить и передать null.

Идея здесь в том, что у нас есть функция, которая будет принимать два массива, a и b и суммировать их вместе. Если a не является массивом, мы берем все аргументы, которые были переданы, и превращаем их в массив, а затем вызываем функцию, снова передающую этот массив как a.

Если a is и array и b не определено, тогда возвращаем функцию, указанную с помощью a.Если a является массивом, а b не является массивом, тогда мы включаем все аргументы (кроме a) и массиваем и вызываем функцию снова. Если b является массивом, мы просто делаем расчет и возвращаем результат.

-1

Еще один способ

function sum() { 
 
    function add(a, b) { 
 
    return a + b; 
 
    }; 
 

 
    var num = [].reduce.call(arguments, add); 
 

 
    function inner() { 
 
    return sum.apply(this, [].concat.apply([num], arguments)); 
 
    } 
 
    inner.toString = inner.valueOf = inner.toJSON = function() { 
 
    return num; 
 
    } 
 
    return inner; 
 
} 
 

 
function o(prepend, val){ 
 
    document.getElementById('res').innerHTML += (prepend? (prepend+": "):"")+(typeof val == 'string'? val : JSON.stringify(val)) + '<br />'; 
 
} 
 

 
o('sum(1,2,3)(4,5,6)(7)',sum(1,2,3)(4,5,6)(7)); 
 
o('sum(1,2,3)',sum(1,2,3)); 
 
o('sum(1)(2,3)', sum(1)(2,3)); 
 
o('sum(1,2)(3)',sum(1,2)(3)); 
 
o('sum(1,2)(3)+"4"',sum(1,2)(3)+"4"); 
 
o('sum(1)(2,3)+4',sum(1)(2,3)+4); //10
<div id="res"></div>

+0

может кто-нибудь объяснить, почему downvote? – Grundy

Смежные вопросы