前端开发面试题—JavaScript回调函数与异步编程

简介: 今天分享一下我遇到的一个面试题,是关于JavaScript回调函数的问题,什么是JavaScript回调函数?

 今天分享一下我遇到的一个面试题,是关于JavaScript回调函数的问题,什么是JavaScript回调函数?

🧇关于回调函数

    • 回调函数就是一个被作为参数传递的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
    • 回调函数的使用可以大大提升编程的效率,这使得它在现代编程中被非常多地使用。同时,有一些需求必须要使用回调函数来实现。
    • 项目开发中,若想要函数体中某部分功能由调用者决定,此时可以使用回调函数。所谓回调函数指的就是一个函数A作为参数传递给一个函数B,然后在B的函数体内调用函数A。此时,我们称函数A为回调函数。如果没有名称(函数表达式),就叫做匿名回调函数,匿名函数常用作函数的参数传递,实现回调函数。

    代码演示

    //part1functioncal(num1, num2, fn) { 
    returnfn(num1, num2);
    }
    //part2console.log(cal(45, 55, function (a, b) {
    returna+b;
    }));
    //part3console.log(cal(10, 20, function (a, b) {
    returna*b;
    }));


    • 上述part1代码定义的cal()函数,用于返回fn回调函数的调用结果。 part2代码用于调用cal()函数,并指定该回调函数用于返回其两个参数相加的结果,因此可在控制台查看到结果为100。同理, part3代码在调用cal()函数时,将回调函数指定为返回其两个参数相乘的结果,因此可在控制台查看到结果为200。
    • 从以上案例可以看出,在函数(如cal()函数)中设置了回调函数后,可以根据调用时传递不同的参数(如相加的函数,相乘的函数等),在函数体中特定的位置实现不同的功能,相当于在函数体内根据用户的需求完成了不同功能的定制。

    🧇两种回调方式

      • 回调可用于数组、计时器函数、promise、事件处理中。
      • 回调的调用方式有两种:同步(阻塞)和异步(非阻塞)回调。

      🚩同步回调

        • 同步回调是“阻塞”的:高阶函数直到回调函数完成后才继续执行。
        • 许多原生 JavaScript 类型的方法都使用同步回调。
        • 最常用的是 array 的方法,例如:array.map(callback),array.forEach(callback),array.find(callback), array.filter(callback), array.reduce(callback, init)
        constpersons= ['Ana', 'Elena'];
        persons.forEach(
        functioncallback(name) {    
        console.log(name);
          }
        );
        //输出'Ana' //输出'Elena'constnameStartingA=persons.find(
        functioncallback(name) {    
        returnname[0].toLowerCase() ==='a';
          }
        );
        console.log(nameStartingA);  // => 'Ana'constcountStartingA=persons.reduce(
        functioncallback(count, name) {    
        conststartsA=name[0].toLowerCase() ==='a';
        returnstartsA?count+1 : count;
        },0);
        console.log(countStartingA);  // => 1
        image.gif

        image.gif

        🚩异步回调

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

        ⏬什么时候用异步编程

          • 在前端编程中(甚至后端有时也是这样),我们在处理一些简短、快速的操作时,例如计算 1 + 1 的结果,往往在主线程中就可以完成。主线程作为一个线程,不能够同时接受多方面的请求。所以,当一个事件没有结束时,界面将无法处理其他请求。
          • 现在有一个按钮,如果我们设置它的 onclick 事件为一个死循环,那么当这个按钮按下,整个网页将失去响应。

          为了避免这种情况的发生,我们常常用子线程来完成一些可能消耗时间足够长以至于被用户察觉的事情,比如读取一个大文件或者发出一个网络请求。因为子线程独立于主线程,所以即使出现阻塞也不会影响主线程的运行。但是子线程有一个局限:一旦发射了以后就会与主线程失去同步,我们无法确定它的结束,如果结束之后需要处理一些事情,比如处理来自服务器的信息,我们是无法将它合并到主线程中去的。

          为了解决这个问题,JavaScript 中的异步操作函数往往通过回调函数来实现异步任务的结果处理

          ⏬使用回调的异步编程

          在最基本的层面上,JavaScript异步编程是使用回调实现的。回调就是函数,可以传给其他函数。而其他函数会在满足某个条件或发生某个(异步)事件时调用(“回调”)这个函数。回调函数被调用,相当于通知你满足了某个条件或发生了某个事件。有时这个调用还会包含函数参数,能提供更多细节。

          ⏬异步回调的例子

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

          setTimeout(functionlater() {
          console.log('123');
          }, 2000);
          // 两秒后输出'123' setInterval(functionrepeat() {
          console.log('123');
          }, 2000);
          // 每两秒输出'123'
          image.gif

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

          constmyButton=document.getElementById('myButton');
          myButton.addEventListener('click', functionhandler() {
          console.log('Button clicked!');
          });
          // 点击按钮后输出'Button clicked!'
          image.gif

          参考来自

          JavaScript中的回调函数看这篇就够了

          JavaScript 异步编程

          目录
          相关文章
          |
          4天前
          |
          资源调度 前端开发 JavaScript
          vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
          【11月更文挑战第10天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤,包括安装依赖、创建混淆脚本、修改 `package.json` 脚本命令、构建项目并执行混淆,以及在 HTML 文件中引用混淆后的文件。通过这些步骤,可以有效提高代码的安全性。
          |
          10天前
          |
          前端开发 JavaScript 开发者
          除了 async/await 关键字,还有哪些方式可以在 JavaScript 中实现异步编程?
          【10月更文挑战第30天】这些异步编程方式在不同的场景和需求下各有优劣,开发者可以根据具体的项目情况选择合适的方式来实现异步编程,以达到高效、可读和易于维护的代码效果。
          |
          11天前
          |
          前端开发 JavaScript 开发者
          深入理解JavaScript异步编程
          【10月更文挑战第29天】 本文将探讨JavaScript中的异步编程,包括回调函数、Promise和async/await的使用。通过实例代码和解释,帮助读者更好地理解和应用这些技术。
          23 3
          |
          12天前
          |
          设计模式 前端开发 JavaScript
          揭秘!前端大牛们如何巧妙利用JavaScript,打造智能交互体验!
          【10月更文挑战第30天】前端开发领域充满了无限可能与创意,JavaScript作为核心语言,凭借强大的功能和灵活性,成为打造智能交互体验的重要工具。本文介绍前端大牛如何利用JavaScript实现平滑滚动、复杂动画、实时数据更新和智能表单验证等效果,展示了JavaScript的多样性和强大能力。
          29 4
          |
          10天前
          |
          前端开发 JavaScript 开发者
          除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
          【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
          |
          21天前
          |
          前端开发 JavaScript UED
          探索JavaScript中的异步编程模式
          【10月更文挑战第21天】在数字时代的浪潮中,JavaScript作为一门动态的、解释型的编程语言,以其卓越的灵活性和强大的功能在Web开发领域扮演着举足轻重的角色。本篇文章旨在深入探讨JavaScript中的异步编程模式,揭示其背后的原理和实践方法。通过分析回调函数、Promise对象以及async/await语法糖等关键技术点,我们将一同揭开JavaScript异步编程的神秘面纱,领略其带来的非阻塞I/O操作的魅力。让我们跟随代码的步伐,开启一场关于时间、性能与用户体验的奇妙之旅。
          |
          25天前
          |
          前端开发 JavaScript 安全
          JavaScript前端开发技术
          JavaScript(简称JS)是一种广泛使用的脚本语言,特别在前端开发领域,它几乎成为了网页开发的标配。从简单的表单验证到复杂的单页应用(SPA),JavaScript都扮演着不可或缺的角色。
          19 3
          |
          3天前
          |
          JavaScript 前端开发
          深入理解Node.js中的异步编程模型
          【10月更文挑战第39天】在Node.js的世界里,异步编程是核心所在,它如同自然界的水流,悄无声息却又无处不在。本文将带你探索Node.js中异步编程的概念、实践以及如何优雅地处理它,让你的代码像大自然的流水一样顺畅和高效。
          |
          7天前
          |
          前端开发 JavaScript 安全
          vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
          【11月更文挑战第7天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤。包括项目准备、安装 `javascript-obfuscator`、配置 Vite 构建以应用混淆,以及最终构建项目进行混淆。通过这些步骤,可以有效提升前端代码的安全性,防止被他人轻易分析和盗用。
          |
          9天前
          |
          前端开发 JavaScript UED
          探索JavaScript的异步编程模式
          【10月更文挑战第33天】在JavaScript的世界里,异步编程是提升应用性能和用户体验的关键。本文将带你深入理解异步编程的核心概念,并展示如何在实际开发中运用这些知识来构建更流畅、响应更快的Web应用程序。从回调函数到Promises,再到async/await,我们将一步步解锁JavaScript异步编程的秘密,让你轻松应对各种复杂的异步场景。