如何避免JavaScript中函数输出的多个变量重新声明

时间:2016-05-04 10:22:30

标签: javascript

考虑以下示例

function doSomethingToAVariable(variable){
    return variable + 1
}

function doSomethingToAVariableASecondTime(variable){
    return variable + 2
}

function doSomethingToAVariableLastly(variable){
    return variable + 3
}

var myVariable = 0;
myVariable = doSomethingToAVariable(myVariable);
myVariable = doSomethingToAVariableASecondTime(myVariable);
myVariable = doSomethingToAVariableLastly(myVariable);

console.log(myVariable); // 6

如何避免令人讨厌的myVariable重新声明?可以将每个函数包装到Promise链中作为解决方案吗?

6 个答案:

答案 0 :(得分:2)

救援的功能组成。
看一下函数式编程库,比如Ramda或lodash-fp。

这里有一个简单的JS片段来组成函数:

//the compose-method you find in your regular FP-libs
var compose = (...funcs) => (value) => funcs.reduceRight((v,fn)=>fn(v), value);
//or a function wich takes the functions in opposite order, 
//wich might be more common to you
var pipe = (...funcs) => (value) => funcs.reduce((v,fn)=>fn(v), value);

compose是您尝试构建的作品的直接映射

var composition = (value) => a(b(c(value)));
var composition = compose(a, b, c);
//it calls the functions from right to left

管道更倾向于您已知的命令式样式,以逐步处理值

var composition = function(value){
    value = c(value);
    value = b(value);
    value = a(value);
    return value;
}
//pipe the value through c, then through b, then through a
var fn = pipe(c, b, a);
//wich in the end does exactly the same as the code built by compose

回到你的代码:

var composition = pipe(
    doSomethingToAVariable,
    doSomethingToAVariableASecondTime,
    doSomethingToAVariableLastly
);
//or
var composition = compose(
    doSomethingToAVariableLastly,
    doSomethingToAVariableASecondTime,
    doSomethingToAVariable
);

//and run it
var myVariable = composition(0);

答案 1 :(得分:1)

如果你想链接,那么你需要返回包含最终值

的对象
function variableOperations( initialValue )
{
  this.value = initialValue;
  this.someOp1 = function(){ this.value += 1; return this; } 
  this.someOp2 = function(){ this.value += 2; return this; } 
}

var a = new variableOperations(1); //new object
a.someOp1().someOp2();

alert(a.value); //alerts 4

答案 2 :(得分:0)

在这种情况下,您正在寻找所谓的“功能组合”:

var myVariable = doSomethingToAVariableLastly(doSomethingToAVariableASecondTime(doSomethingToAVariable(0)));

但使用如此长的函数名称显然无法读取。

Promise通常仅对异步操作有用,虽然它们在这种情况下工作,但结果效率低下并且会在不需要的情况下引入异步依赖:

var promise = doSomethingToAVariable(0);
        .then(doSomethingToAVariableASecondTime);
        .then(doSomethingToAVariableLastly);

因为您只能访问.then回调链末尾的最终结果:

promise.then(function(myVariable) {
    // myVariable is now 6, and in scope
}

// but it's not in scope or usable here

答案 3 :(得分:0)

为什么不看看Ramda的功能方法?

R.compose(
  doSomethingToAVariableLastly,
  doSomethingToAVariableASecondTime,  
  doSomethingToAVariable
)(myVariable)

答案 4 :(得分:0)

以我的拙见,你的代码非常好。

但是,如果你真的想要“链接”这些电话,你可以做这样的事情。但效率稍差。

function chainCalls(initVal, funcs){
  return funcs.reduce(function(val, f){
    return f(val);
  }, initVal || 0);
}

function doSomethingToAVariable(variable){
    return variable + 1
}

function doSomethingToAVariableASecondTime(variable){
    return variable + 2
}

function doSomethingToAVariableLastly(variable){
    return variable + 3
}

var myVariable = chainCalls(0, [doSomethingToAVariable,
                                doSomethingToAVariableASecondTime,
                                doSomethingToAVariableLastly]);

document.write(myVariable);

另一种方法是创建一个像这样的可重用函数链。

function functionChain(){
  var funcs = arguments;
  return function(value){
    return Array.prototype.reduce.call(funcs, function(value, f){
      return f(value);
    }, value);
  };
}

function doSomethingToAVariable(variable){
    return variable + 1
}

function doSomethingToAVariableASecondTime(variable){
    return variable + 2
}

function doSomethingToAVariableLastly(variable){
    return variable + 3
}

var myVariable = functionChain(
  doSomethingToAVariable,
  doSomethingToAVariableASecondTime,
  doSomethingToAVariableLastly
)(0);

document.write(myVariable);

答案 5 :(得分:0)

如果将一些东西放在一起就像递归方法一样简单。有点像使用promises但没有实际使用它们。

function add(x) {
  return {
    done: () => x,
    add: (y) => add(x + y)
  }
}

let myVariable = 0;
add(myVariable).add(1).add(2).add(3).done(); // 6

DEMO