原文来自:https://blog.csdn.net/u011113654/article/details/51672308
今天在网上,看到一篇关于js函数难点的文章,js函数的一些难点。在那上面提了一下,关于js函数返回另一个函数的问题,并附上了一道面试题:
- var add = function(x){
- var sum = 1;
- var tmp = function(x){
- sum = sum + x;
- return tmp;
- }
- tmp.toString = function(){
- return sum;
- }
- return tmp;
- } // alert(add(1)(2)(3)) --> 6
其实我是从java转过来的,一开始看到那篇文章,我对于返回另一个函数并没有什么认识,我之所以写这篇文章是因为,在那里面有一点让我感到奇怪,那就是最后的调用方式
- add(1)(2)(3)
![微笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
我们来看一个最简单的例子:
- function create1(pro) {
- console.log("pro : " + pro);
- return function(obj1, obj2){
- console.log(obj1 + " -- " + obj2);
- return obj1 + obj2;
- }
- }
- var c1 = create1("pro"); // 创建函数
![微笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
。真实的是当我们通过上面的代码调用的时候,日志是打印出了 pro : pro ,但是并没有报错,并且我们反复来回的调用过后,也只是来回的打印相同的日志。这也就说明这个时候,只是进入了create1()方法,并没有进入到该函数的内部函数内。通过面试题的启发,我在试着调用了一次,发现打印出了后续的。
- c1(1, 2); // 调用函数
类似这种函数返回另一个函数的,我们第一次调用只是构建了一个外层函数体对象,只有有后续的调用,才能调用内层函数体,并且重复调用,只会重复内层函数体。
不要急,还没有完,后面还有……
接下来,我们看一看另一种情况,我们先声明一个函数,用来做加法运算:
- function infun(obj1, obj2) {
- console.log(obj1 + " -- " + obj2);
- return obj1 + obj2;
- }
- function create2(pro) {
- console.log("pro = " + pro);
- return infun(obj1, obj2); // 这个时候,会报错
- }
- var c1 = create2("pro");
pro = pro
Uncaught ReferenceError: obj1 is not defined
会发现,打印出了一条日志后,接着抛出了异常。对方法做一下改动,
- function create2(pro) {
- console.log("pro = " + pro);
- var obj1 = 1, obj2 = 2;
- return infun(obj1, obj2); // 这个时候,会报错
- }
这说明,类似于这种,在一个函数内返回一个已经声明的函数,其实是调用已经声明的函数,跟上面的情况是不一样的。
好了,现在回过头来,仔细看看开头的面试题,就会发现一切都明了了:
- // 声明一个函数表达式
- var add = function(x){
- var sum = 1;
- // 在函数表达式内部有一个求和的内部函数
- var tmp = function(x){
- sum = sum + x;// 求和
- return tmp;
- }
- // 构建一个函数体的toString()函数
- tmp.toString = function(){
- return sum;
- }
- return tmp; // 返回的是一个函数体,如果该函数体有toString()方法,则会调用函数体的toString()方法
- }
- alert(add(1)(2)(3))
- // 以下结果输出为:6
- alert(add(10)(2)(3))
- alert(add(100)(2)(3))
- // 下面的结果输出变了
- alert(add(1)(3)(3))
- alert(add(1)(2)(5))
下面附上源码:源码