详细了解JavaScript中的回调函数

详细了解JavaScript中的回调函数

相关推荐:《javascript视频教程》

回调函数是每个前端程序员都应该知道的概念之一。回调可用于数组、计时器函数、promise、事件处理中。

本文将会解释回调函数的概念,同时帮你区分两种回调:同步和异步。

回调函数

首先写一个向人打招呼的函数。

立即学习“Java免费学习笔记(深入)”;

只需要创建一个接受 name 参数的函数 greet(name)。这个函数应返回打招呼的消息:

function greet(name) {  return `Hello, ${name}!`;}greet('Cristina'); // => 'Hello, Cristina!'

登录后复制

如果向很多人打招呼该怎么办?可以用特殊的数组方法  array.map() 可以实现:

const persons = ['Cristina', 'Ana'];const messages = persons.map(greet);messages; // => ['Hello, Cristina!', 'Hello, Ana!']

登录后复制

persons.map(greet) 获取 persons 数组的所有元素,并分别用每个元素作为调用参数来调用 greet() 函数:`greet(‘Cristina’), greet(‘Ana’)。

有意思的是 persons.map(greet) 方法可以接受 greet()  函数作为参数。这样 greet()  就成了回调函数

persons.map(greet) 是用另一个函数作为参数的函数,因此被称为高阶函数

回调函数作为高阶函数的参数,高阶函数通过调用回调函数来执行操作。

重要的是高阶函数负责调用回调,并为其提供正确的参数。

在前面的例子中,高阶函数 persons.map(greet) 负责调用  greet()  函数,并分别把数组中所有的元素 ‘Cristina’ 和 Ana ‘ 作为参数。

这就为识别回调提供了一条简单的规则。如果你定义了一个函数,并将其作参数提供给另一个函数的话,那么这就创建了一个回调。

你可以自己编写使用回调的高阶函数。下面是 array.map() 方法的等效版本:

function map(array, callback) {  const mappedArray = [];  for (const item of array) {     mappedArray.push(      callback(item)    );  }  return mappedArray;}function greet(name) {  return `Hello, ${name}!`;}const persons = ['Cristina', 'Ana'];const messages = map(persons, greet);messages; // => ['Hello, Cristina!', 'Hello, Ana!']

登录后复制

map(array, callback) 是一个高阶函数,因为它用回调函数作为参数,然后在其主体内部调用该回调函数:callback(item)。

注意,常规函数(用关键字 function 定义)或箭头函数(用粗箭头 => 定义)同样可以作为回调使用。

同步回调

回调的调用方式有两种:同步异步回调。

同步回调是“阻塞”的:高阶函数直到回调函数完成后才继续执行。

例如,调用 map() 和 greet() 函数。

function map(array, callback) {  console.log('map() starts');  const mappedArray = [];  for (const item of array) { mappedArray.push(callback(item)) }  console.log('map() completed');  return mappedArray;}function greet(name) {  console.log('greet() called');  return `Hello, ${name}!`;}const persons = ['Cristina'];map(persons, greet);// logs 'map() starts'// logs 'greet() called'// logs 'map() completed'

登录后复制

其中 greet()  是同步回调。

同步回调的步骤:

高阶函数开始执行:’map() starts’

回调函数执行:’greet() called’

.最后高阶函数完成它自己的执行过程:’map() completed’

同步回调的例子

许多原生 JavaScript 类型的方法都使用同步回调。

最常用的是 array 的方法,例如: array.map(callback), array.forEach(callback), array.find(callback), array.filter(callback), array.reduce(callback, init)

// Examples of synchronous callbacks on arraysconst persons = ['Ana', 'Elena'];persons.forEach(  function callback(name) {    console.log(name);  });// logs 'Ana'// logs 'Elena'const nameStartingA = persons.find(  function callback(name) {    return name[0].toLowerCase() === 'a';  });nameStartingA; // => 'Ana'const countStartingA = persons.reduce(  function callback(count, name) {    const startsA = name[0].toLowerCase() === 'a';    return startsA ? count + 1 : count;  },   0);countStartingA; // => 1

登录后复制

字符串类型的 string.replace(callback)  方法也能接受同步执行的回调:

// Examples of synchronous callbacks on stringsconst person = 'Cristina';// Replace 'i' with '1'person.replace(/./g,   function(char) {    return char.toLowerCase() === 'i' ? '1' : char;  }); // => 'Cr1st1na'

登录后复制

异步回调

异步回调是“非阻塞的”:高阶函数无需等待回调完成即可完成其执行。高阶函数可确保稍后在特定事件上执行回调。

在以下的例子中,later() 函数的执行延迟了 2 秒:

console.log('setTimeout() starts');setTimeout(function later() {  console.log('later() called');}, 2000);console.log('setTimeout() completed');// logs 'setTimeout() starts'// logs 'setTimeout() completed'// logs 'later() called' (after 2 seconds)

登录后复制

later() 是一个异步回调,因为 setTimeout(later,2000) 启动并完成了执行,但是 later() 在 2 秒后执行。

异步调用回调的步骤:

高阶函数开始执行:’setTimeout()starts’

高阶函数完成其执行: ‘setTimeout() completed’

回调函数在 2 秒钟后执行: ‘later() called’

异步回调的例子

计时器函数异步调用回调:

setTimeout(function later() {  console.log('2 seconds have passed!');}, 2000);// After 2 seconds logs '2 seconds have passed!' setInterval(function repeat() {  console.log('Every 2 seconds');}, 2000);// Each 2 seconds logs 'Every 2 seconds!'

登录后复制

DOM 事件侦听器还异步调用事件处理函数(回调函数的子类型):

const myButton = document.getElementById('myButton');myButton.addEventListener('click', function handler() {  console.log('Button clicked!');});// Logs 'Button clicked!' when the button is clicked

登录后复制

4.异步回调函数与异步函数

在函数定义之前加上特殊关键字 async 会创建一个异步函数:

async function fetchUserNames() {  const resp = await fetch('https://api.github.com/users?per_page=5');  const users = await resp.json();  const names = users.map(({ login }) => login);  console.log(names);}

登录后复制

fetchUserNames() 是异步的,因为它以 async 为前缀。函数  await fetch(‘https://api.github.com/users?per_page=5’) 从 GitHub 上获取前5个用户 。然后从响应对象中提取 JSON 数据:await resp.json()。

异步函数是 promise 之上的语法糖。当遇到表达式 await  (调用  fetch()  会返回一个promise)时,异步函数会暂停执行,直到 promise 被解决。

异步回调函数和异步函数是不同的两个术语。

异步回调函数由高阶函数以非阻塞方式执行。但是异步函数在等待 promise(await )解析时会暂停执行。

但是你可以把异步函数用作异步回调!

让我们把异步函数 fetch UserNames() 设为异步回调,只需单击按钮即可调用:

const button = document.getElementById('fetchUsersButton');button.addEventListener('click', fetchUserNames);

登录后复制

总结

回调是一个可以作为参数传给另一个函数(高阶函数)执行的函数。

回调函数有两种:同步和异步。

同步回调是阻塞的。

异步回调是非阻塞的。

最后考考你:setTimeout(callback,0) 执行 callback 时是同步还是异步的?

更多编程相关知识,请访问:编程视频!!

以上就是详细了解JavaScript中的回调函数的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2718658.html

(0)
上一篇 2025年3月7日 22:17:46
下一篇 2025年3月7日 22:17:56

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 详解使用 Set 来提高JS代码性能的方法

    我确信有很多开发人员坚持使用基本的全局对象:数字,字符串,对象,数组和布尔值。对于许多用例,这些都是需要的。 但是如果想让你的代码尽可能快速和可扩展,那么这些基本类型并不总是足够好。 在本文中,我们将讨论JS 中Set对象如何让代码更快— …

    2025年3月7日
    000
  • Javascript实现复制动作的几种方法(总结)

    本篇文章给大家介绍一下javascript 实现复制(copy)动作的几种方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 Javascript 实现复制(Copy)动作大全 一、实现点击按钮,复制文本框中的的内容 f…

    2025年3月7日
    200
  • 详解JavaScript降低函数复杂度的方法

    JavaScript 是一种易于学习的编程语言,编写运行并执行某些操作的程序很容易。然而,要编写一段干净的JavaScript 代码是很困难的。 在本文中,我们将研究如何降低函数复杂度。 将重复的代码移到同个位置 我们应该将重复的代码提取出…

    2025年3月7日
    200
  • 怎么遍历DOM

    相关推荐:《javascript视频教程》 我们知道可以使用document对象的内置方法通过ID,类,标签名和查询选择器来访问HTML元素。 DOM 是由节点树构成的,document 节点位于根,其他每个节点(包括元素,注释和文本节点)…

    2025年3月7日
    200
  • jQuery Ajax Post 回调函数不执行怎么办

    回调的JSON数据格式问题,导致回调函数一直无法执行;jQuery Ajax Post 回调函数不执行的解决办法:JSON数据都要用双引号,使用转义字符转义String,代码为【{“hello”:”wor…

    2025年3月7日
    200
  • 实现原生js实现轮播图

    免费学习推荐:javascript视频教程 使用原生js实现轮播图 今天分享一个使用原生JS实现轮播图的案例,并且配上比较详细的过程讲解,欢迎小伙伴的浏览和批评指正。静态效果图如下: 核心思想 将一些图片在一行中平铺,然后计算偏移量再利用定…

    2025年3月7日 编程技术
    200
  • 记录JavaScript的学习笔记

    免费学习推荐:javascript学习教程 一、什么是JavaScript 1-1、JavaScript实现 虽然JavaScript和ECMAScript基本上是同义词,但JavaScript远不限于ECMA-262所定义的那样。完整的J…

    2025年3月7日
    200
  • DOM节点和元素之间有什么区别

    相关推荐:《javascript视频教程》 文档对象模型(DOM)是一个将HTML或XML文档视为树形结构的接口,其中每个节点都是文档的一个对象。DOM还提供了一组方法来查询树、改变结构、样式。 DOM 还使用术语元素(Element)它与…

    2025年3月7日
    200
  • JavaScript实现UTF-8编解码

    免费学习推荐:javascript视频教程 首先简单介绍一下UTF-8。UTF-8以字节为单位对Unicode进行编码。UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完…

    2025年3月7日
    200
  • 实现js的双线性插值和双三次插值法

    免费学习推荐:js视频教程 介绍双线性插值原理双三次插值法原理js实现 介绍 在网页中利用canvas进行绘图时,遇到一个问题,原始的数据分辨率很小,而图片要放大到整个网页,所以需要把数据进行插值放大。学习了双线性插值和三次内插法插值,两种…

    2025年3月7日 编程技术
    200

发表回复

登录后才能评论