js fuction函数内return一个内部函数详解

简介: 今天在网上,看到一篇关于js函数难点的文章,js函数的一些难点。在那上面提了一下,关于js函数返回另一个函数的问题,并附上了一道面试题:[javascript] view plain copy var add = function(x){      var sum = 1;  ...

今天在网上,看到一篇关于js函数难点的文章,js函数的一些难点。在那上面提了一下,关于js函数返回另一个函数的问题,并附上了一道面试题:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. var add = function(x){  
  2.     var sum = 1;  
  3.     var tmp = function(x){  
  4.         sum = sum + x;  
  5.     return tmp;  
  6.     }  
  7.     tmp.toString = function(){  
  8.         return sum;  
  9.     }  
  10.     return tmp;  
  11. // alert(add(1)(2)(3)) --> 6  

接下来,就来详细的解读返回另一个函数的问题。

其实我是从Java转过来的,一开始看到那篇文章,我对于返回另一个函数并没有什么认识,我之所以写这篇文章是因为,在那里面有一点让我感到奇怪,那就是最后的调用方式

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. add(1)(2)(3)  

由于在java中,我没有见到过这样的函数调用方式,所以引起了我的注意,我决定去研究研究;下面就将我的研究分享出来,当然如果你对此已经有了深刻的认识,你可以选择跳过,或者对于不足的地方,给出指点微笑。好了闲话不多说,进入正题。

我们来看一个最简单的例子:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. function create1(pro) {  
  2.     console.log("pro : " + pro);  
  3.     return function(obj1, obj2){  
  4.         console.log(obj1 + " -- " + obj2);  
  5.         return obj1 + obj2;  
  6.     }  
  7. }  

我构建了一个简单的函数create1,并且有一个返回值,返回值是一个内部函数。函数构建完了,接下来进行调用:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. var c1 = create1("pro"); // 创建函数  

如果按照我之前的理解,当我调用了这个方法后,应该会打印出 pro : pro,接着然后报错的。如果你看完过后,也跟我有一样的想法,那恭喜你想多了或者有了固型思维微笑

。真实的是当我们通过上面的代码调用的时候,日志是打印出了  pro : pro ,但是并没有报错,并且我们反复来回的调用过后,也只是来回的打印相同的日志。这也就说明这个时候,只是进入了create1()方法,并没有进入到该函数的内部函数内。通过面试题的启发,我在试着调用了一次,发现打印出了后续的。

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. c1(1, 2); // 调用函数  

这样就打印出了下面的日志;这说明其实我们一开始调用方法的时候,其实是并没有进入到里层的函数的,只是进入了外层函数体,我们只有再调用才能进入里层函数体,并且这个时候,我们重复上面的调用,他只会是调用里层的函数体,并没有外面的函数体。

类似这种函数返回另一个函数的,我们第一次调用只是构建了一个外层函数体对象,只有有后续的调用,才能调用内层函数体,并且重复调用,只会重复内层函数体。
不要急,还没有完,后面还有……

接下来,我们看一看另一种情况,我们先声明一个函数,用来做加法运算:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. function infun(obj1, obj2) {  
  2.     console.log(obj1 + " -- " + obj2);  
  3.         return obj1 + obj2;  
  4. }  

然后再声明一个函数,在该函数中调用上面声明的函数:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. function create2(pro) {  
  2.     console.log("pro = " + pro);  
  3.         return infun(obj1, obj2); // 这个时候,会报错  
  4. }  

最后是调用:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. var c1 = create2("pro");   

查看日志:

pro = pro
‌Uncaught ReferenceError: obj1 is not defined

会发现,打印出了一条日志后,接着抛出了异常。对方法做一下改动,

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. function create2(pro) {  
  2.     console.log("pro = " + pro);  
  3.     var obj1 = 1, obj2 = 2;  
  4.     return infun(obj1, obj2); // 这个时候,会报错  
  5. }  

在调用会发现正常运行,并且打印出了两条日志记录。

这说明,类似于这种,在一个函数内返回一个已经声明的函数,其实是调用已经声明的函数,跟上面的情况是不一样的。
好了,现在回过头来,仔细看看开头的面试题,就会发现一切都明了了:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. // 声明一个函数表达式  
  2. var add = function(x){  
  3.     var sum = 1;  
  4.     // 在函数表达式内部有一个求和的内部函数  
  5.     var tmp = function(x){  
  6.         sum = sum + x;// 求和  
  7.         return tmp;  
  8.     }  
  9.     // 构建一个函数体的toString()函数  
  10.     tmp.toString = function(){  
  11.         return sum;  
  12.     }  
  13.     return tmp; // 返回的是一个函数体,如果该函数体有toString()方法,则会调用函数体的toString()方法  
  14. }  

然后再来看看调用:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. alert(add(1)(2)(3))  

结果为6,至于原因就跟我们第一种讨论的情况一样,接下来,我们反复调用:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片
  1. // 以下结果输出为:6  
  2. alert(add(10)(2)(3))  
  3. alert(add(100)(2)(3))  
  4. // 下面的结果输出变了  
  5. alert(add(1)(3)(3))  
  6. alert(add(1)(2)(5))  


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
3天前
|
JavaScript 前端开发
在JavaScript中,函数原型(Function Prototype)是一个特殊的对象
【5月更文挑战第11天】JavaScript中的函数原型是一个特殊对象,它为所有函数实例提供共享的方法和属性。每个函数在创建时都有一个`prototype`属性,指向原型对象。利用原型,我们可以向所有实例添加方法和属性,实现继承。例如,我们定义一个`Person`函数,向其原型添加`greet`方法,然后创建实例`john`和`jane`,它们都能调用这个方法。尽管可以直接在原型上添加方法,但推荐在构造函数内部定义以封装数据和逻辑。
10 2
|
5天前
|
前端开发 JavaScript 数据处理
在JavaScript中,异步函数是指什么
【5月更文挑战第9天】JavaScript中的异步函数用于处理非立即完成的操作,如定时器、网络请求等。它们可通过回调函数、Promise或async/await来实现。示例展示了如何使用async/await模拟网络请求:定义异步函数fetchData返回Promise,在另一异步函数processData中使用await等待结果并处理。当fetchData的Promise解析时,data变量接收结果并继续执行后续代码。注意,调用异步函数不会阻塞执行,而是会在适当时间点继续。
10 0
|
5天前
|
自然语言处理 JavaScript 前端开发
在JavaScript中,this关键字的行为可能会因函数的调用方式而异
【5月更文挑战第9天】JavaScript中的`this`关键字行为取决于函数调用方式。在非严格模式下,直接调用函数时`this`指全局对象,严格模式下为`undefined`。作为对象方法调用时,`this`指向该对象。用`new`调用构造函数时,`this`指向新实例。通过`call`、`apply`、`bind`可手动设置`this`值。在回调和事件处理中,`this`可能不直观,箭头函数和绑定方法可帮助管理`this`的行为。
10 1
|
5天前
|
JavaScript 前端开发 网络架构
JavaScript中的箭头函数是一种新的函数表达形式
【5月更文挑战第9天】JavaScript的箭头函数以简洁语法简化函数定义,其特性包括:1) 不绑定自身this,继承上下文的this,适合回调和事件处理;2) 没有arguments对象,需用剩余参数语法访问参数;3) 不能用作构造函数,无new调用;4) 没有prototype属性,不支持基于原型的继承。箭头函数在特定场景下优化了this处理,但使用时要注意与普通函数的差异。
8 2
|
8天前
|
JavaScript 前端开发
js的一些内置函数
js的一些内置函数
7 1
|
8天前
|
JavaScript 前端开发 索引
js的includes函数
js的includes函数
12 1
|
8天前
|
JavaScript 安全 前端开发
js的map函数
js的map函数
7 0
|
8天前
|
JavaScript 前端开发
js的filter函数
js的filter函数
10 1
|
8天前
|
JavaScript 前端开发
js的函数
js的函数
7 0
|
8天前
|
JavaScript 前端开发
js的join函数
js的join函数
8 1