js实现无限累加的细节理解

2,260 阅读3分钟
       这段时间找工作也是身心具疲,对于一个才接触前端半年不到的人,秋招真是太不友好了。进入正题,最近在做看一些前端面试帖子,看到了这样的一道题:用js实现一个无限累加的函数add,形如add(1),add(1)(2),add(1)(2)(3),.. 解题原理是在console.log()、alert()的时候,会自动调用toSting方法,输出为字符串形式。

        看代码: 

function add(a){
    function sum(b){
        a = a + b;
        return sum;
    }
    sum.toString = function(){
        return a;
    }
    return sum;
}

 嗯。。这段代码看了许久,没看太明白。输入不同的参数:

add() //undefined
add(10) //f 10
add(10)(20) //f 30

 我们先考虑另外一种情况: 假设 

function add(){};
add.toString = function(){
    return 1;
}

控制台: 

console.log(add) //f 1
console.log(add()) //undefined

       上面的结果很好理解,参数是add的时候,会调用add.toString方法,而我们重写了该方法,所以add.toString返回的是1; 参数是add()的时候,会先执行add函数,而函数体无返回值(等价与return;)所以输出的结果是undefined; 

       若将add函数体改为:

function add(){return add;}

          这时输出就变成了 :

console.log(add) //f 1
console.log(add()) // f 1

 我们试试打印下add()()()()()()()会是啥?结果还是f 1。 可以理解为先执行add(),再返回add;=>add()()()()()();...=>add()=>add.toString(); 我们验证下上面的推断: 

function add(){ 
console.log("add")
return add;
}
add.toString = function(){
    console.log("toString1");
    console.log("toString2");
    return 1;
}
console.log(add()()()()()()())


add打印了7次,最后调用toSrting方法,打印f 1; 但是,为什么toString会被执行两次??为了让问题变得更加清晰,我们改动下toString方法:

                let count = 1;
		add.toString = function(){
			    console.log("toString1");
			    console.log("toString2");
			    console.log(count);
			    count++;
			    if(count == 1) return 1;
			    else return 2;
		}

打印结果为:  


        可以看到,toString执行了两次,且第二次return的结果覆盖了第一次。最后分别再打印输出。至于原因,我的个人理解是第一次toString打印的是f,第二次打印的是2,且优先输出。(我做了一个尝试,在Function的原型上修改toString方法,会打印更多次数。。希望看到的大佬们能解答下,谢谢!)姑且认为改写函数的toString方法后会执行两次。 

        我们再回过头来看 

function add(a){
    function sum(b){
        a = a + b;
        return sum;
    }
    sum.toString = function(){
        return a;
    }
    return sum;
}

 就容易理解了:

add(10): 执行函数add,注意这一次没有调用sum,所以只是返回了sum,再执行sum.toString方法。所以输出10;

 add(10)(20): 执行函数add(10),返回sum(此时a为10),再执行sum(20),此时a为30,返回sum,最后调用sum.toString()输出30。 add(10)(20)...(n)依次类推。 

        问题到这里结束了,留下了个重写toString多次执行的问题,希望有想法的掘友能留下自己的看法。最后,给自己攒一波人品,秋招能拿到offer~~~