当前位置: 首页 > news >正文

深度解析JavaScript面试热点:事件循环、上下文、箭头函数、变量作用域与ES6模块

JavaScript面试中经常涉及到事件循环、上下文、箭头函数、变量作用域以及ES6模块等核心概念。通过清晰的代码示例,我们深入讨论这些主题,揭示其中的关键细节。

事件循环(Event Loop)

JavaScript开发者每天都与事件循环打交道,本文通过实际代码展示了 setTimeoutPromise 和同步代码之间的交互。通过分析回应,我们纠正了一些开发者对于Promise构造函数中执行器函数同步调用的错误观念,同时详细讨论了微任务队列和宏任务队列的执行顺序。

setTimeout(() => console.log(1), 0);console.log(2);new Promise(res => {console.log(3);res();
}).then(() => console.log(4));console.log(5);
// 输出结果:2 3 5 4 1

在这个例子中,我们看到了 setTimeout、Promise 以及一些同步代码。

给定0延迟,我们传递给setTimeout的函数会同步调用还是异步调用?

  • 尽管setTimeout函数有零延迟,回调函数是异步调用的。引擎会将回调函数放在回调队列(宏任务队列)中,并在调用栈为空时将其移至调用栈。因此,数字 1 将被跳过,数字 2 将首先在控制台中显示。

我们作为参数传递给 Promise 构造函数的函数会同步调用还是异步调用?

  • Promise 构造函数接受的函数参数是同步执行的。因此,在控制台中接下来要显示的数字是 3。给定零延迟,我们传递给 promisethen 处理程序的函数会同步调用还是异步调用?

  • then方法中的回调是异步执行的,即使promise没有延迟就解决了。与setTimeout不同的是,引擎会将 promise 回调放在另一个队列中 —— 工作队列(微任务队列),在那里它将等待执行。因此,接下来进入控制台的数字是 5

哪个优先级更高 —— 微任务队列还是宏任务队列,换句话说 —— Promise 还是 setTimeout?

  • 微任务(Promise)比宏任务(setTimeout)有更高的优先级,所以下一个在控制台中的数字将是4,最后一个是1

通过分析回应,我们可以得出结论,大多数受访者在假设传递给 Promise 构造函数作为参数的执行器函数是异步调用的方面是错误的。

上下文(Context)

在面试中,对于 this 关键字的理解至关重要。我们通过具体的例子讨论了普通函数和箭头函数中 this 的不同行为,并解释了在不同上下文中函数调用的结果。

普通函数
'use strict';function foo() {console.log(this);
}function callFoo(fn) {fn();
}let obj = { foo };callFoo(obj.foo);
// 输出结果:undefined
箭头函数

深入研究了箭头函数内部的 this 值,展示了它与普通函数之间的差异。通过实例强调箭头函数不能作为构造函数使用的限制,以及它们在原型属性上的行为。

'use strict';
var x = 5;
var y = 5;function Operations(op1 = x, op2 = y) {this.x = op1;this.y = op2;
};Operations.prototype.sum = () => this.x + this.y;const op = new Operations(10, 20);console.log(op.sum());
// 输出结果:10

箭头函数没有自己的 this。相反,箭头函数体内的 this 指向该箭头函数定义所在作用域的this 值。

我们的函数是在全局作用域中定义的。

全局作用域中的 this 指向全局对象(即使在严格模式下也是如此)。因此,答案是 10

另一个关于箭头函数的问题可能是这样的。

const Num = () => {this.getNum = () => 10;
}Num.prototype.getNum = () => 20;const num = new Num();console.log(num.getNum());

箭头函数不能用作构造函数,当使用 new 调用时会抛出错误。它们也没有原型属性:

TypeError:无法设置undefined的属性(设置'getNum')

这样的问题比较少见,但你应该为它们做好准备。你可以在 MDN 上查看更多关于箭头函数的信息。

变量作用域

通过临时死区、变量声明提升等概念,详细探讨了变量作用域。通过具体的代码案例,让读者更好地理解在不同作用域中变量的行为。

'use strict';console.log(foo());let bar = 'bar';function foo() {return bar;
}bar = 'baz';
// 输出结果:ReferenceError: bar is not defined

let / const变量定义之前的作用域中的位置被称为临时死区。

如果我们在 let / const 变量定义之前尝试访问它们,将会抛出引用错误。

这种行为是因为 const 变量而被选中的。访问未定义的 var 变量时,我们得到的是undefined。对于 const 变量来说,这是不可接受的,因为它将不再是一个常量。

let 变量的行为以类似的方式完成,以便您可以轻松地在这两种类型的变量之间切换。

回到我们的例子。

由于函数调用在 bar 变量的定义之上,该变量处于临时死区。

代码抛出一个错误:

ReferenceError:初始化前不能访问'bar'

let func = function foo() {return 'hello';
}console.log(typeof foo);

在命名函数表达式中,名称只在函数体内部是局部的,外部无法访问。因此,全局作用域中不存在foo

typeof运算符对未定义的变量返回undefined

function foo(bar, getBar = () => bar) {var bar = 10;console.log(getBar());
}foo(5);

对于具有复杂参数(解构、默认值)的函数,参数列表被封闭在其自己的作用域内。

因此,在函数体中创建 bar 变量不会影响参数列表中同名的变量,getBar() 函数通过闭包从其参数中获取 bar。

一般来说,我们注意到尽管ES6已经发布了7年多,但开发人员对其特性的理解仍然很差。当然,每个人都知道这个版本中特性的语法,但只有少数人能更深入地理解它。

ES6模块

对ES6模块的导入机制进行了解析,强调了导入会被提升的特性。通过示例,展示了模块间依赖的加载顺序。

console.log('index.js');import { sum } from './helper.js';console.log(sum(1, 2));
// 输出结果:helper.js index.js 3

导入会被提升。

提升是JS中的一种机制,其中变量和函数声明在代码执行之前被移动到它们的作用域的顶部。

所有依赖项将在代码运行之前加载。

所以,答案是:helper.js index.js 3

'use strict';var num = 8;function num() {return 10;
}console.log(num);

函数和变量声明被放在其作用域的顶部,变量的初始化发生在脚本执行时。

具有相同名称的变量的重复声明将被跳过。

函数总是首先被提升。无论函数和具有相同名称的变量的声明在代码中以何种顺序出现,函数都优先,因为它上升得更高。

示例1

function num() {}
var num;
console.log(typeof num); // function

示例2

var num;
function num() {}
console.log(typeof num); // function

变量总是在最后被初始化。

var num = 8; function num() {}

将被转换为:

function num() {}
var num; // repeated declaration is ignored
num = 8;

结果,num = 8。

提高难度

import foo from './module.mjs';console.log(typeof foo);-------------------------
foo = 25;export default function foo() {}

结果export default function foo() {}

等于

function foo() {}
export { foo as default }

在引擎处理完模块代码后,你可以将其想象成以下形式:

function foo() {}
foo = 25;
export { foo as default }

所以正确答案是数字。

Promises

最后,通过一个Promise链的例子,深入讨论了Promise的执行过程,特别是在抛出错误和使用 catch 处理程序时的执行流程。

Promise.resolve(1).then(x => { throw x }).then(x => console.log(`then ${x}`)).catch(err => console.log(`error ${err}`)).then(() => Promise.resolve(2)).catch(err => console.log(`error ${err}`)).then(x => console.log(`then ${x}`));
// 输出结果:error 1 then 2

这篇文章通过清晰的代码示例和深度解析,为读者提供了深入理解JavaScript核心概念的机会,是面试前的必读材料。

相关文章:

深度解析JavaScript面试热点:事件循环、上下文、箭头函数、变量作用域与ES6模块

JavaScript面试中经常涉及到事件循环、上下文、箭头函数、变量作用域以及ES6模块等核心概念。通过清晰的代码示例,我们深入讨论这些主题,揭示其中的关键细节。 事件循环(Event Loop) JavaScript开发者每天都与事件循环打交道&am…...

Javaweb之Mybatis的动态SQL的详细解析

3. Mybatis动态SQL 3.1 什么是动态SQL 在页面原型中,列表上方的条件是动态的,是可以不传递的,也可以只传递其中的1个或者2个或者全部。 而在我们刚才编写的SQL语句中,我们会看到,我们将三个条件直接写死了。 如果页面…...

物联网与智能家居:跨境电商与未来生活的融合

物联网(Internet of Things,IoT)和智能家居技术正迅速崛起,成为跨境电商领域的创新引擎。这两者的巧妙结合不仅为消费者提供更智能、便捷的生活方式,同时也为电商平台和制造商带来了全新的商机。本文将深入探讨物联网与…...

Java内存模型(JMM)是基于多线程的吗

Java内存模型(JMM)是基于多线程的吗 这个问题按我的思路转换了下,其实就是在问:为什么需要Java内存模型 总结起来可以由几个角度来看待「可见性」、「有序性」和「原子性」 面试官:今天想跟你聊聊Java内存模型&#…...

Linux离线安装MySQL(rpm)

目录 下载安装包安装MySQL检测安装结果服务启停MySQL用户设置 下载安装包 下载地址:https://downloads.mysql.com/archives/community/ 下载全量包如:(mysql-8.1.0-1.el7.x86_64.rpm-bundle.tar) 解压:tar -xzvf mysql-8.1.0-1.el7.x86_64.…...

用 Socket.D 替代原生 WebSocket 做前端开发

socket.d.js 是基于 websocket 包装的 socket.d 协议的实现。就是用 ws 传输数据,但功能更强大。 功能原生 websocketsocket.d说明listen有有监听消息send有有发消息sendAndRequest无有发消息并接收一个响应(类似于 http)sendAndSubscribe无…...

Transformer架构和对照代码详解

1、英文架构图 下面图中展示了Transformer的英文架构,英文架构中的模块名称和具体代码一一对应,方便大家对照代码、理解和使用。 2、编码器 2.1 编码器介绍 从宏观⻆度来看,Transformer的编码器是由多个相同的层叠加⽽ 成的,每个…...

大数的乘法

题目描述 求两个不超过100位的非负整数的乘积。 输入 有两行,每行是一个不超过100位的非负整数,没有多余的前导0。 输出 一行,相乘后的结果。 样例输入 Copy 123456789 123456789样例输出 Copy 15241578750190521 代码实现&#xff1…...

年度征文 | 机器学习之心的2023

机器学习之心的2023 2023是极其复杂的一年。 生活上,养了很多宠物。 工作上,写了不少博客。 虽然遇见更多让人不开心的事情,但总体还是美好的。 愿大家新的一年健康平安,生活幸福! 机器学习是一项庞大的工程&#xff0…...

13.Kubernetes应用部署完整流程:从Dockerfile到Ingress发布完整流程

本文以一个简单的Go应用Demo来演示Kubernetes应用部署的完整流程 1、Dockerfile多阶段构建 Dockerfile多阶段构建 [root@docker github]# git clone https://gitee.com/yxydde/http-dump.git [root@docker github]# cd http-dump/ [root@docker http-dump]# cat Dockerfile …...

多年后再用TB,谈项目管理工具

背景 最近启动一个小项目,多年未曾使用项目管理工具,依稀记得使用过Basecamp,Tower,worktitle,teambition等等,当然还有mantis,vs project等等。于是随便翻阅找个用,不小心翻了TB的牌子,竟然已是阿里旗下的…...

Spark MLlib ----- ALS算法

补充 在谈ALS(Alternating Least Squares)之前首先来谈谈LS,即最小二乘法。LS算法是ALS的基础,是一种数优化技术,也是一种常用的机器学习算法,他通过最小化误差平方和寻找数据的最佳匹配,利用最小二乘法寻找最优的未知数据,保证求的数据与已知的数据误差最小。LS也被用…...

ubuntu桥接方式上网

vmvare:VMware Workstation 17 Pro ubuntu: Ubuntu 14.04.6 LTS window10 下面是我的电脑配置 下面是ubuntu虚拟机的配置 vi /etc/network/interfaces 下面的gateway就是window -ipconfig 截图里的默认网关 auto lo iface lo inet loopbackauto eth0 iface eth0 inet stat…...

收到的字符串写入xml并且将这个xml写入.zip文件中

文章目录 1、将数据写入xml文件WriteToXmlFile2、将xml文件写入zip压缩文件AddToZip3、组合起来4、使用到的头文件和动态库 1、将数据写入xml文件WriteToXmlFile void CSMSLoginDlg::WriteToXmlFile(const std::string& responseData, const std::string& xmlFileName…...

【读书笔记】《白帽子讲web安全》跨站脚本攻击

目录 前言: 第二篇 客户端脚本安全 第3章 跨站脚本攻击(XSS) 3.1XSS简介 3.2XSS攻击进阶 3.2.1初探XSS Payload 3.2.2强大的XSS Payload 3.2.2.1 构造GET与POST请求 3.2.2.2XSS钓鱼 3.2.2.3识别用户浏览器 3.2.2.4识别用户安装的软…...

第九节 初始化项目

系列文章目录 目录 系列文章目录 前言 操作方法 总结 前言 初始化项目,导入默认reset.scss 、variables.scss及mixins.scss等并修改main.js引入样式 操作方法 将默认样式表文件导入到项目。样式文件已经放到资源里请自行下载(...

【论文阅读】深度学习中的后门攻击综述

深度学习中的后门攻击综述 1.深度学习模型三种攻击范式1.1.对抗样本攻击1.2.数据投毒攻击1.3.后门攻击 2.后门攻击特点3.常用术语和标记4.常用评估指标5.攻击设置5.1.触发器5.1.1.触发器属性5.1.2.触发器类型5.1.3.攻击类型 5.2.目标类别5.3.训练方式 1.深度学习模型三种攻击范…...

Spring Boot中加@Async和不加@Async有什么区别?设置核心线程数、设置最大线程数、设置队列容量是什么意思?

在 Spring 中,Async 注解用于将方法标记为异步执行的方法。当使用 Async 注解时,该方法将在单独的线程中执行,而不会阻塞当前线程。这使得方法可以在后台执行,而不会影响主线程的执行。 在您提供的代码示例中,a1() 和…...

Vue_00001_CLI

初始化脚手架 初始化脚手架步骤: 第一步(仅第一次执行):全局安装vue/cli。 命令:npm install -g vue/cli 第二步:切换到要创建项目的目录,然后使用命令创建项目。 命令:vue creat…...

kubernetes ResourceQuotas Limits(资源配额)

开头语 写在前面:如有问题,以你为准, 目前24年应届生,各位大佬轻喷,部分资料与图片来自网络 内容较长,页面右上角目录方便跳转 简介 当多个用户或团队共享具有固定节点数目的集群时,人们会…...

【ARMv8架构系统安装PySide2】

ARMv8架构系统安装PySide2 Step1. 下载Qt资源包Step2. 配置和安装Qt5Step3. 检查Qt-5.15.2安装情况Step4. 安装PySide2所需的依赖库Step5. 下载和配置PySide2Step6. 检验PySide2是否安装成功 Step1. 下载Qt资源包 if you need the whole Qt5 (~900MB): wget http://master.qt…...

ECMAScript6详解

ECMAScript 6,也被称为 ES6 或 ECMAScript 2015,是 JavaScript 编程语言标准的一个主要更新。它于 2015 年正式发布,并带来了许多新特性和改进,使得 JavaScript 开发更加现代化和高效。下面是 ES6 的一些关键特性的详解&#xff1…...

[C#]使用PaddleInference图片旋转四种角度检测

官方框架地址】 https://github.com/PaddlePaddle/PaddleDetection.git 【算法介绍】 PaddleDetection 是一个基于 PaddlePaddle(飞桨)深度学习框架的开源目标检测工具库。它提供了一系列先进的目标检测算法,包括但不限于 Faster R-CNN, Ma…...

stable diffusion 基础教程-提示词之光的用法

基图 prompt: masterpiece,best quality,1girl,solo,looking at viewer,brown hair,hair between eyes,bangs,very long hair,red eyes,blush,bare shoulders,(white sundress),full body,Negative prompt: EasyNegative,badhandv4,nsfw,lowres,bad anatomy,bad hands,text…...

第9课 回声抑制(AEC+AGC+ANS)的实现

在第8课中,我们将推流端与播放端合并实现了一对一音视频聊天功能,一切看起来还不错。但在实际使用时,会遇到一个烦心的问题:说话时会听到比较大的回声,影响正常使用。所以,这节课我们来重点解决这个问题。 …...

软件测试|Python中的变量与关键字详解

简介 在Python编程中,变量和关键字是非常重要的概念。它们是构建和控制程序的基本要素。本文将深入介绍Python中的变量和关键字,包括它们的定义、使用方法以及一些常见注意事项。 变量 变量的定义 变量是用于存储数据值的名称。在Python中&#xff0…...

修改安卓apk设置为安卓主屏幕(launcher)

修改安卓apk 将apk可以设置安卓主屏幕 原理: 将打包好的apk文件进行拆包增加配置文件在重新编译回apk包 需要得相关文件下载 解包 apktool :https://pan.baidu.com/s/1oyCIYak_MHDJCvDbHj_qEA?pwd5j2xdex2jar:https://pan.baidu.com/s/1Nc-0vppVd0G…...

unity中 canvas下物体的朝向跟随

public Transform target; private Vector3 direction; void Update() { //第一种 //direction target.position - transform.position; //transform.up -direction.normalized; //第二种 if (target ! null ) { …...

HarmonOS 日期选择组件(DatePicker)

本文 我们一起来看基础组件中的 DatePicker 这就是 日程开发中的日期组件 他可以创建一个日期的范围 并创建一个日期的滑动选择器 这里 我们先写一个组件的骨架 Entry Component struct Index {build() {Row() {Column() {}.width(100%)}.height(100%)} }然后 我们先在Column组…...

linux中的系统安全

一.账号安全 将非登录用户的shell设为/sbin/nologin 系统中用户有三种:超级管理员 普通用户 程序用户 前两种用户可以登录系统,程序用户不给登录 所以称为非登录用户 命令格式: usermod -s /sbin/nologin(改已有用户&#…...

wordpress附件上传云/搜资源

使用微信云开发 官方介绍文档 开发者可以使用云开发开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力。云开发为开发者提供完整的云端支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务…...

做电销哪些网站可以找到客户端/中国搜索引擎市场份额

php与数据库之间的链接,用数据库里的数据 将数据库的数据添加到HTML语句中转载于:https://www.cnblogs.com/huzhen/p/3712880.html...

wordpress微信登录页面/搜索网站排名

这一节中我们演示下solr中创建多核的另一种方法。 接第10讲,首先关闭tomcat服务器 1.解压solr-4.8.0后,找到solr-4.8.0下面的example文件夹下的multicore文件夹 2. 把multicore文件夹下的所有文件拷贝到D:\Server\Solr文件夹下面 3.启动tomcat服务器&…...

建设银行官方网站个人/百度安全中心

Linux命令reboot:重启指令systemctl:查看所有的服务touch 文件名:新建文件rm 文件名:删除文件clear:清空终端内容ll:显示当前得目录vim 文件名:类似记事本可以进行编辑vim 的指令操作正常模式&a…...

哪些官网用wordpress/百度录入网站

2019独角兽企业重金招聘Python工程师标准>>> web.xml报错Invalid content was found starting with element init-param. 原文来自:http://www.blogjava.net/Mitool/archive/2010/11/20.html。 转载到这里作为备用,转载请注明原文出处。 …...

wordpress投稿送积分/怎么做网页

日常开发运维的过程中,我们总是会遇到各样重复性劳动而这些工作占据了我们大量时间。我们一定都经历过这样的场景:每一次产品迭代更新,都要一遍遍「打包-上传-登录服务器-替换-部署-重启」重复的类似工作;在本地 IDE、云产品控制台…...