2024年前端面试中JavaScript的30个高频面试题之高级知识

基础知识
中级知识
21. 什么是执行上下文,执行堆栈,变量对象和作用域链?

执行上下文: 执行上下文是指代码执行的环境。它由作用域,变量对象和“this”关键字的值组成。

每当一个函数被执行时,就会创建一个执行上下文,并包含该函数的所有变量或属性。

JavaScript中有三种类型的执行上下文:

全局执行上下文

函数执行上下文

Eval函数执行上下文

**执行栈:**也称为“调用栈”,是一个LIFO(后进先出)数据结构,用于存储正在进行的函数调用的所有执行上下文。当调用一个函数时,会为该函数创建一个新的执行上下文并推送到栈中。当函数完成时,其上下文将从栈中弹出。

引擎执行堆栈顶部上下文对应的函数。当这个函数完成时,它的执行栈将从栈中弹出,控制权达到它下面的当前堆栈中的上下文。

执行上下文在创建阶段创建。在创建阶段会发生以下事情:

  1. LexicalEnvironment 组件被创建。

  2. VariableEnvironment 组件被创建。

变量对象: 是执行上下文的一部分,包含该上下文中定义的所有变量、函数声明和参数。

作用域链: 作用域链是解析 JavaScript 中变量值的一种机制。当引用一个变量时,JavaScript 引擎会首先在当前执行上下文的变量对象中查找该变量。如果没有找到,则继续在外层执行上下文的作用域链上查找,直到找到该变量或到达全局执行上下文。

22. 回调函数、promise、setTimeout和process.nextTick()的执行优先级是什么?

通过事件循环和不同异步操作的处理顺序,可以理解执行优先级:

  1. process.nextTick(): 使用process.nextTick()调度的回调具有最高优先级。当您使用process.nextTick()时,回调会在当前操作完成后、事件循环移动到下一阶段之前立即执行。这是确保函数在事件循环中尽可能早地执行的一种方式。

  2. Promise: Promise通常在process.nextTick()之后执行。但是,它们的优先级高于使用setTimeout()调度的回调。

  3. setTimeout(): 使用setTimeout()调度的回调被放置在事件循环的定时器阶段。它们将在当前操作、promise和任何以前调度的setTimeout()回调完成后执行。

  4. Callback: 常规回调(未使用process.nextTick()调度)具有最低优先级。它们会在事件循环处理完process.nextTick()、promise和setTimeout()回调后执行。

23. 什么是工厂函数和生成器函数?

JavaScript中的工厂函数是一个返回对象的函数。这是一种使用简单且有组织的方式创建对象的模式。工厂函数封装了对象创建过程,并返回一个新对象,而不是使用构造函数和new关键字来创建新对象。

function createPerson(name, age) {return {name: name,age: age,greet: function() {return `Hello, my name is ${this.name} and I am ${this.age} years old.`;}};
}const person1 = createPerson('Alice', 25);
const person2 = createPerson('Bob', 30);console.log(person1.greet()); // 输出:Hello, my name is Alice and I am 25 years old.
console.log(person2.greet()); // 输出:Hello, my name is Bob and I am 30 years old.

生成器函数在 JavaScript 中是一种特殊类型的函数,可以在执行期间暂停和恢复。

生成器函数会产生一个结果序列而不是单个值。

当调用生成器函数时,它会返回一个生成器对象,可以使用 next() 方法来控制函数的执行。

可以使用 yield 关键字在函数体内暂停代码,并在以后从暂停的地方恢复执行。

function* numberGenerator() {let i = 0;while (true) {yield i++;}  
}const gen = numberGenerator();
console.log(gen.next().value); // 输出:0  
console.log(gen.next().value); // 输出:1
console.log(gen.next().value); // 输出:2

这为创建迭代器和处理异步代码提供了强大的机制。

24. 复制(浅复制和深复制)对象的不同方法?

浅复制 是对象的一份拷贝,其引用与原始对象相同。这意味着如果改变浅复制中的属性值,也会改变原始对象中的属性值。

const user = {    name: "Kingsley",age: 28,job: "Web Developer"
}
const clone = user  

深复制 是对象的一份拷贝,其引用与原始对象不同。这意味着如果改变深复制中的属性值,不会改变原始对象中的属性值。

有不同的方法可以深复制一个对象。

a)JSON.parse 和 JSON.stringify:对嵌套对象也有用。

   const originalObject = { name: "Alice", age: 25 };const deepCopy = JSON.parse(JSON.stringify(originalObject));

b)structuredClone:

const myDeepCopy = structuredClone(myOriginal); 

c)Spread Operator(…): 任何包含嵌套对象的对象都不会深度复制。

const originalObject = { name: "Alice", age: 25 };
const deepCopy =  {...originalObject};  deepCopy.name = "ravi"
console.log("originalObject", originalObject.name) // Alice

d)Object.assign(): 应该使用 Object.assign()方法来深复制没有嵌套对象的对象。

const originalObject = { name: "Alice", age: 25 };
const shallowCopy = Object.assign({}, originalObject);

e)Recursion:

   function deepCopy(obj) {if (typeof obj !== 'object' || obj === null) {return obj;}const newObj = Array.isArray(obj) ? [] : {};for (let key in obj) {if (Object.hasOwnProperty.call(obj, key)) {newObj[key] = deepCopy(obj[key]);}}return newObj;}const originalObject = { name: "Alice", nested: { age: 25 } };const deepCopy = deepCopy(originalObject);

25. 如何使一个对象不可变?(seal 和 freeze 方法)?

在 JavaScript 中,可以使用 Object.seal() 和 Object.freeze() 方法使对象不可变。

Object.freeze() 😦完全不可变) 这个方法冻结了一个对象,既封闭了该对象,又将其所有属性标记为只读。在冻结对象之后,其属性不能被修改、添加或删除。

     const obj = { name: 'Alice', age: 25 };Object.freeze(obj); obj.name = 'Bob'; // 不允许  obj.address = '123 Street'; // 不允许delete obj.age; // 不允许

Object.seal():(部分不可变) 这个方法封闭了一个对象,防止添加新属性并将所有现有属性标记为不可配置。但是,您仍然可以修改那些可写的现有属性的值。

     const obj = { name: 'Alice', age: 25 }; Object.seal(obj);obj.name = 'Bob'; // 允许obj.address = '123 Street'; // 不允许(不能添加新属性) delete obj.age; // 不允许(不能删除现有属性)

26. 什么是事件和事件流?事件冒泡和事件捕获是什么?

在 JavaScript 中,事件流是指类似点击或按键等事件在网页或浏览器中被接收或处理的顺序。事件流中有两个阶段:事件捕获和事件冒泡。

当您点击嵌套在各种其他元素中的元素时,在点击实际到达其目标或目标元素之前,它必须首先触发其每个父元素的点击事件,从顶部的全局窗口对象开始。

<div id="parent"><button id="child">Click me!</button> 
</div>

现在,让我们用这个例子来解释事件流:

  1. 事件捕获阶段: 当您单击按钮时,事件从顶部开始(文档的根部),向下移动到目标元素。在这种情况下,它从文档的根目录遍历到 <div>(父元素),然后到 <button>(子元素)。这称为捕获阶段。

  2. 事件目标阶段: 事件到达目标元素,在这种情况下是 <button>

  3. 事件冒泡阶段: 在到达目标后,事件开始向上冒泡。它从 <button>回到 <div>,最终到达文档的根目录。这称为冒泡阶段。

以下是简单的 JavaScript 代码片段,可见此过程的实际运行:

document.getElementById('parent').addEventListener('click', function() {console.log('Div clicked (capturing phase)'); 
}, true); // 这里的 'true' 表示捕获阶段。 
document.getElementById('child').addEventListener('click', function() {console.log('Button clicked (target phase)'); 
});document.getElementById('parent').addEventListener('click', function() {console.log('Div clicked (bubbling phase)');
});

当您单击按钮时,控制台中会按以下顺序显示这些消息:

  1. “Div clicked (capturing phase)”
  2. “Button clicked (target phase)”
  3. “Div clicked (bubbling phase)”

27. 什么是事件委托?

事件委托是一种优化多个元素的事件处理的 JavaScript编程技术。

它不是为每个单独的元素附加事件侦听器,而是将单个事件监听器附加到 DOM (文档对象模型)层次结构中更高级别的公共祖先元素。

当发生在后代元素之一的事件时,它会“冒泡”到公共祖先元素,事件侦听器正在那里等待。

事件委托是一种监听事件的技术,其中您将父元素委托为其中发生的所有事件的侦听器。

var form = document.querySelector("#registration-form");
// 监听表单内部的字段更改
form.addEventListener(  "input",function (event) {// 记录更改的字段  console.log(event.target);},false
);

28. 什么是服务器发送的事件?

服务器发送事件(SSE)是一种简单高效的技术,可以通过单个 HTTP 连接从服务器端实时更新客户端。

SSE 允许服务器在有新信息可用时立即将数据推送到 Web 客户端(通常是浏览器),非常适合需要实时更新而不依赖复杂协议或第三方库的场景。

a)SSE 提供从服务器到客户端的单向数据流。服务器发起通信,向客户端发送更新。

b)SSE **使用基于文本的协议,**这意味着从服务器发送到客户端的数据通常以文本格式(通常是 JSON 或纯文本)。

c)SSE 自动处理重连。

d)SSE 在客户端和服务器端建立持久连接,允许服务器向客户端发送一串事件。每个事件都可以具有唯一的类型和相关的数据。

e)EventSource 对象用于接收服务器发送的事件通知。 例如,您可以如下接收来自服务器的消息:

if (typeof EventSource !== "undefined") {var source = new EventSource("sse_generator.js");source.onmessage = function (event) {document.getElementById("output").innerHTML += event.data + "<br>";};
}

f)以下是服务器发送事件的事件列表(onopen、onmessage、onerror)。

29. 什么是 web worker 或 service worker?

Web Worker 和 Service Worker 是 JavaScript 中的两个不同概念:

Web Worker 用于并发 JavaScript 后台执行,而 Service Worker 用于创建具有离线功能的渐进式 Web 应用程序和高级功能。这两者都是增强 Web 应用程序性能和功能的重要工具。

它们各自在 Web 开发中起distinct 作用:

Web Worker:

  1. 并发: Web Worker 是浏览器功能,允许您在主浏览器线程之外的后台运行 JavaScript 代码。这实现了任务的并发执行,而不阻塞用户界面。

  2. 使用案例: Web Worker 常用于计算密集型或时间消耗型任务,如数据处理、图像操作或复杂计算。通过在单独的线程中运行这些任务,它们不会影响网页的响应能力。

  3. 通信: Web Worker 可以使用消息传递系统与主线程通信。它们可以发送和接收消息,允许主线程和 Worker 协调。

  4. 浏览器支持: 大多数现代浏览器都支持 Web Worker。

Service Worker:

  1. 脱机功能: Service Worker 是用于创建渐进式 Web 应用程序 (PWA) 的更高级功能。它们充当代理服务器,在后台运行并可拦截和缓存网络请求。这支持脱机功能,例如在用户脱机时提供缓存内容。

  2. 使用案例: Service Worker 主要用于实现脱机访问推送通知和后台同步等功能。它们使 Web App 即使在没有互联网连接的情况下也能正常运行。

  3. 生命周期:Service Worker 有自己的生命周期,具有 installactivatefetch 等事件。它们通常在 Web App 的生命周期开始时注册。

  4. 浏览器支持:Service Worker 在现代浏览器中得到支持,是创建可靠和引人入胜的 Web 应用程序的关键技术。

30. 如何比较两个 JSON 对象?

a) 一种简单的方法是使用 JSON.stringify 将它们转换为字符串,然后比较字符串。

function areEqual(obj1, obj2) {return JSON.stringify(obj1) === JSON.stringify(obj2);
}const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };  
console.log(areEqual(obj1, obj2)); // 输出:true

b) 您也可以使用 Ramda 库来比较两个 JSON 对象。Ramda 提供了一个名为 equals 的函数。

const R = require('ramda');const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };console.log(R.equals(obj1, obj2)); // 输出:true 

c) 另一种选择是使用一个库,比如 Lodash,它提供了一种对象进行深度比较的方法。

const _ = require('lodash');const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
console.log(_.isEqual(obj1, obj2)); // Output: true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/617625.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为机试真题实战应用【赛题代码篇】-路灯照明(附Java、C++和python代码)

目录 问题描述 思路解析 思路1 思路2 代码实现 C++ 代码2

多无人机编队避障(人工势场法)

matlab2020正常运行&#xff0c;预设编队类型&#xff0c;目标位置&#xff0c;障碍物 多无人机编队避障&#xff08;人工势场法&#xff09;资源-CSDN文库

树莓派ubuntu:新增用户

切换到Root用户 sudo -i创建新用户 useradd -m 新用户名设置密码 passwd 新用户名将新用户加入sudo用户组 adduser newname sudo拷贝数据 cp -R /home/旧用户名/* /home/新用户名/查看用户所属组 id 新用户名更改文件所属 sudo chown 新用户名:group /home/新用户名/*gr…

浅析链表结构

一、单向链表 C语言中数组是常用的一种数据类型&#xff0c;但可惜数组长度是固定大小的&#xff0c;不能动态扩展&#xff0c;使用起来有时不是很方便。然后就有了自定义的动态数组结构&#xff0c;动态数组就比较好用了&#xff0c;长度可以任意扩展&#xff0c;但还有一个问…

easyexcel 3.0.x 版本实现指定列 锁定以及指定列隐藏

1&#xff1a;效果示例 2&#xff1a;代码示例&#xff1a; UnLockCell.java package com.example.juc.zhujie;/*** Author * Date Created in 2023/12/19 10:09* DESCRIPTION:* Version V1.0*/import java.lang.annotation.*;/*** 用于标记锁定哪些列不需要锁定* author 12…

YOLOv8改进 | 检测头篇 | 利用DySnakeConv改进检测头专用于分割的检测头(全网独家首发,Seg)

一、本文改进 本文给大家带来的改进机制是一种我进行优化的专用于分割的检测头,在分割的过程中,最困难的无非就是边缘的检测,动态蛇形卷积(Dynamic Snake Convolution)通过自适应地聚焦于细长和迂回的局部结构,准确地捕捉管状结构的特征。这种卷积方法的核心思想是,通过…

【LangChain学习之旅】—(7) 调用模型:使用OpenAI API还是微调开源Llama2/ChatGLM?

【LangChain学习之旅】—&#xff08;7&#xff09; 调用模型&#xff1a;使用OpenAI API还是微调开源Llama2/ChatGLM&#xff1f; 大语言模型发展史预训练 微调的模式用 HuggingFace 跑开源模型申请使用 Meta 的 Llama2 模型通过 HuggingFace 调用 LlamaLangChain 和 Hugging…

若依在表格中如何将字典的键值转为中文

文章目录 一、需求&#xff1a;二、问题解决步骤1、给需要转换的列绑定formatter属性2、获取字典项3、编写formatter属性绑定的方法 一、需求&#xff1a; 后端有时候返回的是字典的键值&#xff0c;在前端展示时需要转成中文值 后端返回的是dictValue&#xff0c;现在要转换…

【Git】本地仓库文件的创建、修改和删除

目录 一、基本信息设置 1、设置用户名2、设置用户名邮箱 二、Git仓库操作介绍 1、创建一个新的文件夹2、在文件内初始化git仓库&#xff08;创建git仓库&#xff09;3、向仓库中添加文件 1.创建一个文件2.将文件添加到暂存区3.将暂存区添加到仓库 4、修改仓库文件 1.修改文件2.…

java中数组

文章目录 java中数组思维导图数组数组概念 数组定义格式详解数组的访问 常见异常数组索引值越界异常&#xff1a;ArrayIndexOutOfBoundsException空指针异常&#xff1a;NullPointerException 案例例一打印A-Z和0-9例二数组转置输出 java中数组 思维导图 数组 数组概念 组就…

Java8常用新特性

目录 简介 1.默认方法 2..Lambda表达式 3.Stream API 4.方法引用 5.Optional类 简介 Java 8是Java编程语言的一个重要版本&#xff0c;引入了许多令人兴奋和强大的新特性。这些特性使得Java程序更加现代化、灵活和高效。让我们一起来探索一些Java 8的常用新特性吧&#…

NestJS 如何自定义中间件以及实际项目基于中间件提升项目开发效率

前言 NestJS 作为一个强大的 Node.js 框架&#xff0c;允许你通过中间件对请求和响应进行处理。中间件的概念在其他许多框架中也存在&#xff0c;它们在请求处理流程的早期执行&#xff0c;因此非常适合执行如日志记录、请求验证、设置响应头等任务。 在这篇教程中&#xff0…

Mac 下载 nvm 后执行nvm -v 命令报错 nvm: command not found

1、问题&#xff1a;Mac 使用命令下载nvm 成功后执行 nvm -v 查看&#xff0c;报错&#xff1a;nvm command not found 2、原因&#xff1a;可能是系统更新后&#xff0c;默认的 shell 是 zsh&#xff0c;所以找不到配置文件 3、解决&#xff1a;可添加编辑.bash_profile 和 …

回归和拟合的关系

在统计学和机器学习中&#xff0c;回归&#xff08;Regression&#xff09;和拟合&#xff08;Fitting&#xff09;是密切相关的概念&#xff0c;它们通常一起使用来描述如何通过模型来逼近或拟合数据。 回归&#xff08;Regression&#xff09;&#xff1a; 回归是一种统计学…

Docker 安装部署

1、Docker 安装 ① 卸载docker&#xff0c;清空之前的docker文件 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-selinux \docker-engine-selinux \docker-engine \docker-ce…

2021腾讯、华为前端面试题集(基础篇)

Vue 面试题 生命周期函数面试题 1.什么是 vue 生命周期2.vue 生命周期的作用是什么 3.第一次页面加载会触发哪几个钩子 4.简述每个周期具体适合哪些场景 5.created 和 mounted 的区别 6.vue 获取数据在哪个周期函数 7.请详细说下你对 vue 生命周期的理解&#xff1f; **vue 路由…

达梦数据库主备集群

1&#xff1a;服务器硬件需求 按实际业务需求&#xff0c;选择合适的服务器&#xff0c;准备 3 台服务器&#xff0c;一台主库服务器&#xff0c;一台备库服务器&#xff0c;一台监视器服务器&#xff0c;服务器参数建议如下&#xff1a; 硬件要求物理内存>16 GB交换区Swa…

MySQL同步ES的几种方案

MySQL数据同步ES的几种方案 1. 同步双写 与业务耦合深&#xff0c;且业务响应时间长 2. 异步双写 这时可以使用类似MQ这样的中间件&#xff0c;业务主写时向MQ发送一条信息&#xff0c;再由一个聚合服务区消费&#xff0c;最终同步到ES 3. 定时任务 不好配置时间&#xff0c;…

Spring Boot - Application Events 的发布顺序_ContextRefreshedListener

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c;它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…

2024年最新软件测试面试题

Part1 1、你的测试职业发展是什么&#xff1f;【文末有面试文档免费领取】 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做…