Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/440.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中的闭包-出了什么问题?_Javascript_Closures - Fatal编程技术网

JavaScript中的闭包-出了什么问题?

JavaScript中的闭包-出了什么问题?,javascript,closures,Javascript,Closures,我试图在下一步结束时: 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 但我有一个错误:未捕获类型错误:数字不是函数您

我试图在下一步结束时:

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
但我有一个错误:未捕获类型错误:数字不是函数

您误用了函数

func(2)
返回
res
函数。
使用
(3)
调用该函数将返回数字
5
(通过
返回结果+num

5
不是一个函数,因此
(4)
给出了一个错误。

嗯,(2)(3)部分是正确的。调用func(2)将返回
res
,这是一个函数。但是,调用(3)将返回
res
的结果,这是一个数字。所以当你试着打电话(4)时,问题就来了


对于您试图做的事情,我不知道Javascript如何预测您处于链的末端,并决定返回一个数字而不是一个函数。也许您可以使用对象属性返回一个具有“result”属性的函数,但我最想知道的是,为什么您要这样做。显然,对于您的特定示例,最简单的方法就是将数字相加,但我猜您在某些方面做得更进一步。

如果您想继续调用它,您需要不断返回函数,直到您需要答案为止。e、 g.用于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
函数func(数字){
var结果=数字,
迭代=0,
fn=函数(num){
结果+=num;
如果(++迭代<4),则返回fn;
返回结果;
};
返回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
函数func(数字){
var结果=数字,
fn=函数(){
var i;
对于(i=0;i
您必须以某种方式通知链的末端,在那里您将返回结果编号,而不是另一个函数。您可以选择:

  • 让它返回一个固定次数的函数——这是使用语法的唯一方法,但它很无聊。看看@PaulS的答案。您可以进行第一次调用(
    func(n)
    )来提供参数数量
    sum
  • 在某些情况下返回结果,例如在调用函数时没有参数(@PaulS的第二个实现)或使用特殊值(
    null
    在@AmoghTalpallikar的答案中)
  • 在函数对象上创建一个返回值的方法
    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
    

我将此标记为重复,但由于该问题中也缺少此选项,我将在此处添加它。如果我正确理解了为什么您会认为这很有趣(具有一个顺序应用于值列表的任意函数,累积结果),您还应该查看
reduce

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

a = [2, 3, 4, 5, 3];

b = a.reduce(sum);

另一种解决方案可能只是调用不带params的函数以获得结果,但如果使用params调用函数,则会将其添加到总和中

函数添加(){
var总和=0;
var闭包=函数(){
sum=Array.prototype.slice.call(参数).reduce(函数总数,num){
返回total+num;
},总和);
return arguments.length?闭包:sum;
};
返回closure.apply(null,参数);
}
console.log(添加(1,2,7)(5)(4)(2,3)(3.14,2.86));//函数(){}

console.log(添加(1,2,7)(5)(4)(2,3)(3.14,2.86)();//30;
我们可以使用两个助手函数
identity
sumk
轻松实现它

sumk
使用一个continuation来保存挂起的add计算堆栈,并在调用第一个
()
时使用
0
展开堆栈

const identity=x=>x
常数sumk=(x,k)=>
x==未定义?k(0):y=>sumk(y,next=>k(x+next))
const sum=x=>sumk(x,恒等式)
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
这伤害了我的大脑。。您可以返回一个函数或一个数字,而不是两者都返回。@MikeChristensen:实际上,您可以通过检查
参数来返回这两个函数。length
@SLaks-Oh并在链的末尾放一个
()
?是的,这是一个惹恼同事的聪明方法。你有什么理由不能使用
func(2,3,4,5,3)
并修改你的函数以适应这种设置吗?虽然你有一个简单的例子,但这样做更有意义,而不是不断调用函数?…可能是@user2056866的重复。很难看出这有什么实际用途,所以这很可能是家庭作业。你想做一个递归函数吗?如果是这样的话,你就有点不对劲了。只是为了有趣,我试图通过闭包来完成这个任务。@user2056866:试试我的答案。这不完全是你想要的,但几乎是一样的。是的,这只是为了有趣。但我还是不明白怎么会是对的。就像我说的,你用这种方式称呼它的整个方法都很奇怪。返回具有链可调用函数的对象会更容易接受吗?例如,
func().addmore(3).addmore(5).addmore(7).getResult()
?这通常是JQuery所做的。我并没有对您的答案投反对票,但它只适用于这么多的()。它不是动态的。@AmoghtalPalikar好吧,我是为OPs编写的,但在我的版本中,它的工作原理略有不同。如果我打电话。f(4)(5)结果变为9。nxt时间f(