[英]Closure in JavaScript - whats wrong?
我试图通过关闭来制作下一个:
function func(number) {
var result = number;
var res = function(num) {
return result + num;
};
return res;
}
var result = func(2)(3)(4)(5)(3);
console.log(result); // 17
我需要收到 2 + 3 + 4 + 5 + 3 = 17 但我收到一个错误:未捕获的 TypeError: number is not a function
您必须以某种方式指示链的末端,您将在此处返回结果编号而不是另一个函数。 你有选择:
func(n)
) 提供curried参数sum
的数量。null
)的情况下调用函数时。 在函数对象上创建一个返回值的方法。 valueOf()
非常适合,因为它会在函数被转换为原始值时被调用。 看看它在行动:
function func(x) { function ret(y) { return func(x+y); } ret.valueOf = function() { return x; }; return ret; } func(2) // Function func(2).valueOf() // 2 func(2)(3) // Function func(2)(3).valueOf() // 5 func(2)(3)(4)(5)(3) // Function func(2)(3)(4)(5)(3)+0 // 17
你在滥用你的功能。
func(2)
返回res
函数。
使用(3)
调用该函数会返回数字5
(通过return result + num
)。
5
不是函数,所以(4)
给出错误。
好吧,(2)(3)部分是正确的。 调用 func(2) 将返回res
,这是一个函数。 但是,调用 (3) 将返回res
的结果,这是一个数字。 因此,当您尝试调用 (4) 时,问题就来了。
对于您正在尝试做的事情,我看不出 Javascript 如何预测您处于链的末端,并决定返回一个数字而不是一个函数。 也许您可以使用对象属性以某种方式返回一个具有“结果”属性的函数,但大多数情况下,我只是好奇您为什么要以这种方式做事。 显然,对于您的具体示例,最简单的方法就是将数字相加,但我猜您会更进一步。
如果你想继续调用它,你需要不断返回一个函数,直到你想要你的答案。 例如 5 次调用
function func(number) {
var result = number,
iteration = 0,
fn = function (num) {
result += num;
if (++iteration < 4) return fn;
return result;
};
return fn;
}
func(2)(3)(4)(5)(3); // 17
你也可以做一些像这样工作的更多长度
function func(number) {
var result = number,
fn = function () {
var i;
for (i = 0; i < arguments.length; ++i)
result += arguments[i];
if (i !== 0) return fn;
return result;
};
return fn;
}
func(2)(3, 4, 5)(3)(); // 17
我将其标记为重复,但由于该问题也缺少此替代方案,因此我将在此处添加它。 如果我理解正确,为什么您会认为这很有趣(将任意函数顺序应用于值列表,累积结果),您还应该研究reduce
:
function sum(a, b) {
return a + b;
}
a = [2, 3, 4, 5, 3];
b = a.reduce(sum);
另一种解决方案可能只是调用不带参数的函数以获得结果,但如果你使用参数调用它,它会增加总和。
function add() { var sum = 0; var closure = function() { sum = Array.prototype.slice.call(arguments).reduce(function(total, num) { return total + num; }, sum); return arguments.length ? closure : sum; }; return closure.apply(null, arguments); } console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)); // function(){} console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)()); // 30;
我们可以使用几个辅助函数identity
和sumk
。
sumk
使用延续来保留一个待处理的添加计算的堆栈,并在调用 first ()
时用0
展开堆栈。
const identity = x => x const sumk = (x,k) => x === undefined ? k(0) : y => sumk(y, next => k(x + next)) const sum = x => sumk(x, identity) console.log(sum()) // 0 console.log(sum(1)()) // 1 console.log(sum(1)(2)()) // 3 console.log(sum(1)(2)(3)()) // 6 console.log(sum(1)(2)(3)(4)()) // 10 console.log(sum(1)(2)(3)(4)(5)()) // 15
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.