JS - 回调函数

简介: JS - 回调函数

【1】函数亦对象

在javascript中,函数是比较奇怪的,但它确确实实是对象。确切地说,函数是用Function()构造函数创建的Function对象。Function对象包含一个字符串,字符串包含函数的javascript代码。

对于javascript来说,数据和代码之间的区别是很模糊的。故你可以把函数作为参数在函数间传递—函数的回调。

示例如下:

var fn = new Function("arg1", "arg2", "return arg1 * arg2;");
fn(2, 3); //6
typeof fn === 'function';
instanceof fn === 'object';

【2】回调函数的调用

显示回调函数调用

示例一如下:

function a(callback){
   alert("这是parent函数a");
   var m =1;
   var n=3;
   //注意这里,为回调函数传参。
  return callback(m,n);
 }
 //b作为a的回调函数
 function b(m,n){
   alert("这是回调函数B");
   return m+n;
 }
 // 父函数执行
 $(function(){
     //回调函数作为父函数的参数
   var result = a(b);
   alert("result = "+ result);
 });

执行结果如下:

这是parent函数a
这是回调函数B
result = 4

示例一中,b函数作为回调函数在适当时机在a函数内部被调用,并使用了a函数内部的局部变量

在JS-闭包中,说明了闭包常用的两种形式:函数作为返回值,函数作为参数传递。

调函数的实现形式恰好符合!!

这意味着回调函数本质上是一个闭包。正如我们所知,闭包能够进入包含它的函数的作用域,因此回调函数能获取包含它的函数中的变量,以及全局作用域中的变量。

使用全局变量实现形式如下:

//定义全局变量
var m =1;
var n=3;
function a(callback){
   alert("这是parent函数a");
   //注意这里,使用全局变量为回调函数传参。
  return callback(m,n);
 }
 //上同....

匿名回调函数调用

示例二如下:

function foo(){
 var a = 10;
 //匿名回调函数
 return function(){
  a *= 2;
  return a;  
 }; 
}
var f = foo();
f(); //return 20.
f(); //return 40.

或如下:

$("#testA").click(function(){
    //doSomething;
});

其中click函数内部使用了匿名函数作为参数,该匿名函数作为click函数的回调函数。


【3】回调函数参数

三种形式:使用全局变量参数;使用父函数参数;传回调函数的时候同时传参数;

示例一 - 全局变量—–参考【2】中使用全局变量形式

示例二 - 局部变量—–参考【2】中示例一

示例三 - 同时传递回调函数和参数如下:

//定义父函数
function a(callback,param){
    callback(param);
}
//定义回调函数
function b(param){
    return param+2;
}
//执行函数
a(b,2);//4

注意,不能在回调函数作为参数的时候同时赋予参数;即如下示例错误 :

//错误示例
a(b(2));
//正确示例
a(b,2);//4

【4】判断回调函数

最好保证回调存在且必须是函数引用或者函数表达式:

if(callback && typeof(callback) === "function"){             
    callback();
}

【5】回调函数中的call()和apply()

JS 中函数都有call() apply()方法。说明如下:

call方法:

语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 
定义:调用一个对象的一个方法,以另一个对象替换当前对象;即调用对象替换被调用对象。 

call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply方法:

语法:apply([thisObj[,argArray]]) ;
定义:应用某一对象的一个方法,用另一个对象替换当前对象。 

需要注意的是:如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。 这是与call()参数使用的不同之处。


如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。


修改上文中的例子如下:

<script type="text/javascript">
     // 父函数执行
     $(function(){
         //回调函数作为父函数的参数
       var result = a(b);
       console.log("result = "+ result);
     });
     function a(callback){
           console.log("这是parent函数a");
           var m =1;
           var n=3;
           //注意这里,为回调函数传参。
//        return callback(m,n);
           console.log(callback.call(this,m,n));
           console.log(this);
           return callback.apply(this,[m,n]);
         }
     //b作为a的回调函数
     function b(m,n){
       console.log("这是回调函数B");
       return m+n;
     }
</script>

结果如下:


修改call方法和b函数如下:

<script type="text/javascript">
     // 父函数执行
     $(function(){
         //回调函数作为父函数的参数
       var result = a(b);
       console.log("result = "+ result);
     });
     function a(callback){
           console.log("这是parent函数a");
           var m =1;
           var n=3;
            //将this指向b函数
           console.log(callback.call(b,m,n));
           //a函数上下文中的this--window
           console.log(this);
           return callback.apply(this,[m,n]);
         }
     //b作为a的回调函数
     function b(m,n){
       console.log("这是回调函数B");
          //此处this将会是b函数自身
        console.log(this);
       return m+n;
     }
</script>

结果如下:

当一个函数自执行的时候,this指向的是window,当需要改变这个指向的时候,让函数call执行即可。

call函数执行的时候,第一个参数代表函数内部的this指向,传递的第二个参数对应函数的第一个参数,以此类推。

同样,你可以使用apply()函数改变this指向并传参。

使用场景:

当回调函数是一个含有this对象的方法时,我们必须修改执行回调函数的方法以保护this对象的内容。否则this对象将会指向全局的window对象(如果回调函数传递给了全局函数),或指向包含函数



目录
相关文章
|
4月前
|
JavaScript 前端开发 Go
动态加载与异步加载 JavaScript 详解:加载远程js,加载成功后执行回调函数
动态加载与异步加载 JavaScript 详解:加载远程js,加载成功后执行回调函数
749 2
|
4月前
|
JavaScript 前端开发 UED
在 JavaScript 中,异步编程和回调函数是处理非阻塞操作(如网络请求、文件读写等)的重要工具
【5月更文挑战第10天】JavaScript中的异步编程和回调函数用于处理非阻塞操作,提高应用响应性和吞吐量。异步编程通过回调函数、Promises和async/await等方式实现,避免程序因等待操作完成而阻塞。回调函数是异步操作完成后调用的函数,常用于处理网络请求等。然而,回调函数存在嵌套问题和错误处理困难,因此出现了Promises和async/await等更优解决方案。
39 3
|
2月前
|
JavaScript 前端开发 API
Node中的AsyncLocalStorage 使用问题之Node.js将 JavaScript 层的 nativeHooks 注册到 C++ 层的问题如何解决
Node中的AsyncLocalStorage 使用问题之Node.js将 JavaScript 层的 nativeHooks 注册到 C++ 层的问题如何解决
|
3月前
|
存储 前端开发 JavaScript
回调函数是JavaScript中处理异步编程的常见模式,常用于事件驱动和I/O操作。
【6月更文挑战第27天】回调函数是JavaScript中处理异步编程的常见模式,常用于事件驱动和I/O操作。它作为参数传递给其他函数,在特定条件满足或任务完成后被调用。例如,`asyncOperation`函数接受回调函数`handleResult`,模拟异步操作后,调用`handleResult`传递结果。这样,当异步任务完成时,`handleResult`负责处理结果。
28 1
|
3月前
|
前端开发 JavaScript
JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。
【6月更文挑战第22天】JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。回调是基础,用于在操作完成后执行函数;Promise管理异步状态,支持链式调用;async/await提供同步代码外观,简化错误处理。每种技术在处理耗时任务时都起着关键作用。
32 3
|
3月前
|
前端开发 JavaScript 开发者
JavaScript基础-异步编程:回调函数
【6月更文挑战第12天】本文介绍了JavaScript中的异步编程基础,重点讨论回调函数。回调函数是处理延迟操作的关键,常见于事件监听、定时器、Ajax请求和文件操作。然而,它们可能导致回调地狱、错误处理不一致和控制流混乱等问题。为了解决这些问题,文章推荐使用Promise链、async/await来扁平化异步逻辑,并提供了相关代码示例,强调了现代JavaScript特性的优势,以提升代码可读性和可维护性。
78 7
|
3月前
|
JavaScript API
Node.js 回调函数
Node.js 回调函数
23 1
|
2月前
|
JavaScript
JS 你可能没用过的【回调函数式替换】replace()
JS 你可能没用过的【回调函数式替换】replace()
33 0
|
3月前
|
前端开发 JavaScript 开发者
JavaScript异步编程艺术:深入浅出回调函数与异步挑战【含代码示例】
本文深入解析JavaScript异步编程,重点探讨回调函数和异步挑战。在单线程的JavaScript中,异步编程至关重要,回调函数是其基础。然而,回调地狱问题催生了Promise和async/await的出现。文章提供代码示例展示Promise和async/await的使用,并分享异步编程最佳实践,包括错误处理、资源管理和性能优化。遇到问题时,建议通过明确异步流程、逐步调试和异常捕获来解决。最后,文章强调异步编程的未来发展,鼓励开发者掌握最新工具并探讨更高效的异步解决方案。
67 2
|
4月前
|
前端开发 JavaScript 开发者
在JavaScript中,回调函数是一种非常强大的工具
【5月更文挑战第10天】JavaScript中的回调函数是异步编程的核心,常用于处理异步操作结果、事件监听、定时任务、数组遍历和转换以及递归调用。例如,`fetchData`函数使用回调处理网络请求的结果,`addEventListener`用于监听事件,`setTimeout`执行延迟任务,`map`则对数组元素进行操作。尽管回调函数可能导致回调地狱和错误处理复杂,但它们依然是理解和掌握JavaScript的关键技能,而Promise和async/await提供了更优的异步解决方案。
30 2