我被要求创建一个函数来实现以下内容,加上一些数字然后调用它们的全部值,即一个链接的函数,我创建了一个糟糕的解决方案,但想不出更好的做法此
add(5).add(10).add(20).value();
面试问题刚开始是空函数
function add() {
}
我的解决方案如下,是否有任何其他建议,因为我感兴趣,我看了currying,绑定等,但没有提出一个优雅的解决方案。
var slice = Array.prototype.slice
function add() {
var arr = slice.call(arguments);
return {
add: function() {
arr = arr.concat(slice.call(arguments))
return this;
},
value: function() {
return arr.reduce(function(prev, curr) {
return prev + curr;
});
}
}
};
修改 只是为了澄清我想知道是否有办法在不返回添加函数的情况下执行此操作,而是调用现有的add函数。我认为下面的方式很好,但我认为面试官正在寻找一些不简单的东西。
答案 0 :(得分:7)
为什么这么复杂?不要随身携带这些价值观。此外,尽量保持功能并且不要改变它。
function add(x) {
return {
value: function() {
return x;
},
add: function(y) {
return add(x+y);
}
};
}
这里的关键见解似乎是链接并不仅仅意味着return this
,而是同一类的任何对象。不变性决定了当它附加不同的总和时它应该是一个不同的对象。
答案 1 :(得分:0)
看起来过于复杂,这是我的答案,但也许我不理解要求的一部分
function add(x) {
return {
val: 0,
add: function(x) {
this.val += x;
return this;
},
value: function() {
return this.val;
}
}
};
答案 2 :(得分:0)
我喜欢懒惰计算的想法,这就是我们应该保持操作链的原因。但是使用数组的实现具有可变性的缺点(参见我的评论)
我刚刚写了一些关于我如何看待解决方案
的文章var Calculator = function(initialValue){
function createOperator(operation) {
return function(value) {
return createInstance(operation.bind(null, value));
}
}
function createInstance(reduce) {
return Object.freeze({
'add': createOperator((val) => reduce() + val),
'subtract': createOperator((val) => reduce() - val),
'multiply': createOperator((val) => reduce() * val),
'divide': createOperator((val) => reduce() / val),
'value': reduce
});
}
return createInstance(()=>initialValue);
}
Calculator(0).add(5).multiply(4).subtract(12).divide(2).value(); //returns 4
在你的问题中,懒惰的计算并不是真正需要的,但是如果我们想要保留多个用途的操作链,那么就在这里。见这个例子
var Calculation = function(){
function createOperator(operation) {
return function(value) {
return createInstance(operation.bind(null, value));
}
}
function createInstance(apply) {
return Object.freeze({
'add': createOperator((val, initial) => apply(initial) + val),
'subtract': createOperator((val, initial) => apply(initial) - val),
'multiply': createOperator((val, initial) => apply(initial) * val),
'divide': createOperator((val, initial) => apply(initial) / val),
'apply': apply
});
}
return createInstance((initialValue)=>initialValue);
}();
var calc = Calculation.add(5).multiply(2).subtract(11);
calc.apply(2); //returns 3
calc.apply(10); //returns 19