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

中级
高级知识

充分准备你的下一个JavaScript面试,增强信心!

无论你是老手还是刚进入技术行业,这份2024年必备资源都将帮助你复习核心概念,从基本语言特性到高级主题。

在本文中,我汇总了30个最关键的JavaScript面试题以及详细的答案和代码示例。

深入探索这宝贵的收藏,以确保JavaScript面试的顺利进行,在当今竞争激烈的技术行业保持领先地位。

一、基础知识

  1. JavaScript是单线程的吗?

  2. 解释JavaScript引擎的主要组成部分及其工作原理。

  3. 解释JavaScript中的事件循环及其如何帮助异步编程。

  4. var、let和const的区别是什么?

  5. JavaScript中的不同数据类型?

  6. 什么是回调函数和回调地狱?

  7. 什么是Promise和Promise链?

  8. 什么是async/await?

  9. = =和= = =运算符有什么区别?

  10. 在Javascript中创建对象的不同方法?

  11. 什么是rest和spread运算符?

  12. 什么是高阶函数?

二、中级知识

  1. 什么是闭包?闭包的用例有哪些?

  2. 解释JavaScript中的变量提升概念。

  3. 什么是暂时性死区?

  4. 什么是原型链?以及Object.create()方法?

  5. Call、Apply和Bind方法的区别是什么?

  6. 什么是lambda或箭头函数?

  7. 什么是柯里化函数?

  8. ES6的特性有哪些?

三、专家级知识

  1. 什么是执行上下文、执行堆栈、变量对象和作用域链?

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

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

  4. 对象的浅拷贝和深拷贝的不同方法?

  5. 如何使对象不可变?(封装和冻结方法)

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

  7. 什么是事件委托?

  8. 什么是服务端推送事件?

  9. web worker或服务工作线程是什么?

  10. 如何在javascript中比较两个JSON对象?

=============================================

1. JavaScript是否为单线程?

是的,JavaScript是一种单线程语言。这意味着它只有一个调用堆栈和一个内存堆。一次只执行一组指令。

此外,Javascript本质上是同步和阻塞的。这意味着代码逐行执行,一个任务必须在下一个任务开始之前完成。

然而,JavaScript也具有异步功能,允许独立于主执行线程执行某些操作。这通常通过回调、promise、async/await和事件侦听器等机制来实现。这些异步功能使得JavaScript能够处理数据获取、用户输入和I/O操作等任务,而不会阻塞主线程,因此适合构建响应迅速和交互性强的Web应用程序。

2. 解释JavaScript引擎的主要组成部分及其工作原理

每个浏览器都有一个JavaScript引擎,它执行javascript代码并将其转换为机器代码。

当执行JavaScript代码时,解析器首先读取代码并生成AST,并将其存储在内存中。然后解释器处理这个AST并生成字节码或机器代码,由计算机执行。

分析器是JavaScript引擎的一个组件,用于监控代码的执行。

字节码与性能分析数据一起用于优化编译器。”优化编译器“或即时(JIT)编译器根据分析数据的假设生成高度优化的机器代码。

有时,“优化”假设不正确,然后它通过“取消优化”阶段(这实际上成为我们的开销)返回到以前的版本。

JS引擎通常会优化“热函数”,并使用内联缓存技术来优化代码。

在此过程中,调用堆栈跟踪当前正在执行的函数,内存堆用于内存分配

最后,垃圾回收器开始发挥作用,通过回收未使用对象的内存来管理内存。

Google Chrome V8引擎:

  1. 解释器称为**“点火装置”**。
  2. 优化编译器称为**“涡轮风扇”**。
  3. 除解析器外,还引入了“预解析器”,用于检查语法和标记
  4. 在“点火装置”和“涡轮风扇”之间引入了**“火花塞”,也称为快速编译器**。

3. 解释JavaScript中的事件循环

事件循环是JavaScript运行时环境的核心组件。它负责调度和执行异步任务。事件循环通过持续监控两个队列来工作:调用堆栈和事件队列。

调用堆栈是一个堆栈(LIFO)数据结构,用于存储当前正在执行的函数调用的所有执行上下文(存储代码执行期间创建的执行上下文)。

Web API是异步操作(setTimeout、fetch请求、promise)及其回调正在等待完成的地方。它从线程池中借用线程在后台完成任务,而不会阻塞主线程。

**作业队列(或微任务)是一个FIFO(先进先出)结构,用于保存异步/等待的回调函数、promise、process.nextTick()**等准备执行的回调。例如,fulfilled promise的resolve或reject回调会进入作业队列。

**任务队列(或宏任务)是一个FIFO(先进先出)结构,用于保存异步操作回调(计时器像setInterval、setTimeout)**等准备执行的回调。例如,超时的setTimeout()回调准备执行,会进入任务队列。

事件循环会永久监控调用堆栈是否为空。如果调用堆栈为空,事件循环会查看作业队列或任务队列,并将任何准备执行的回调出队到调用堆栈中

4. var、let和const的区别是什么?

在浏览器中,window对象是浏览器窗口,HTML树中的顶级结构。使用var全局声明的变量会附加到window对象上。在浏览器控制台中键入var dog = ‘bowser’,然后键入window.dog.。值“bowser”出现了!这使得控制变量作用域变得更加困难。相比之下,let和const没有附加到window对象上。

5. JavaScript中的不同数据类型?

JavaScript是一种动态和松散类型化的语言,也称为鸭子类型语言。这意味着我们不需要指定变量的类型,因为JavaScript引擎会根据其值动态确定变量的数据类型。

JavaScript中的基本数据类型是最基本的数据类型,用于表示单个值。它们是**不可变的(不能更改)**并直接包含特定的值。

在JavaScript中,Symbol是一个原始数据类型,在ECMAScript 6(ES6)中引入,代表一个唯一和不可变的值。它通常用作对象属性的标识符,以避免名称冲突。

const mySymbol = Symbol('key');const obj = {[mySymbol]: 'value'};

当Symbol用作属性键时,它与其他属性键(包括字符串键)不会发生冲突。

6. 什么是回调函数和回调地狱?

在JavaScript中,回调函数通常用于处理异步操作。

回调函数是一个作为参数传递给另一个函数的函数,旨在在完成特定任务或在给定时间后执行

function fetchData(url, callback) {// 模拟从服务器获取数据setTimeout(() => {const data = 'Some data from the server';callback(data);}, 1000);
}function processData(data) {console.log('Processing data:', data);
}fetchData('https://example.com/data', processData);

在这个例子中,fetchData函数有两个参数:URL和一个回调函数。在从服务器获取数据(使用setTimeout模拟)后,它调用回调函数并将检索到的数据传递给它。

回调地狱,也称为**“金字塔”,是一个术语,用于描述在异步函数中使用多个嵌套回调**的情况。

它发生在异步操作取决于以前的异步操作结果的情况下,导致代码嵌套深度增加,通常难以阅读。

回调地狱是一个反模式,其中有多个嵌套的回调,这使得代码在处理异步逻辑时难以阅读和调试。

fs.readFile('file1.txt', 'utf8', function (err, data) {if (err) {console.error(err);} else {fs.readFile('file2.txt', 'utf8', function (err, data) {if (err) {console.error(err);} else {fs.readFile('file3.txt', 'utf8', function (err, data) {if (err) {console.error(err);} else {// Continue with more nested callbacks...}});}});}
});

在这个例子中,我们使用fs.readFile函数顺序读取三个文件,每个文件读取操作都是异步的。因此,我们必须将回调嵌套在另一个回调中,创建一个回调金字塔。

**要避免回调地狱,现代的 JavaScript 提供了 Promises 和 async/await 等替代方案。**下面是使用 Promises 的相同代码:

const readFile = (file) => {return new Promise((resolve, reject) => {fs.readFile(file, 'utf8', (err, data) => {if (err) {reject(err);} else {resolve(data);}});});
};
readFile('file1.txt').then((data1) => {return readFile('file2.txt');}).then((data2) => {return readFile('file3.txt');}).then((data3) => {// Continue with more promise-based code...}).catch((err) => {console.error(err);});

7. 什么是Promise和Promise链?

Promise: Promise是JavaScript中的一个对象,用于异步计算。它表示异步操作的结果,该结果可能被解析或拒绝

Promise有三种状态:

  1. Pending:初始状态。该状态下Promise的最终值还不可用。
  2. Fulfilled:成功解析状态。该状态下promise成功地解析了最终值,该值现在是可用的。
  3. Rejected:遇到错误或被拒绝状态。该状态下promise无法提供最终值。

Promise构造函数有两个参数**(resolve, reject),这些参数都是函数**。如果异步任务已成功完成且没有错误,则使用消息或获取的数据调用resolve函数来解析promise。

如果发生错误,请调用reject函数并将错误传递给它。

我们可以使用.then()处理程序访问promise的结果。

我们可以在.catch()处理程序中捕获错误。

// 创建一个Promise
const fetchData = new Promise((resolve, reject) => {// 模拟从服务器获取数据setTimeout(() => {const data = 'Some data from the server';// 使用检索到的数据解析Promiseresolve(data);// 使用错误拒绝Promise// reject(new Error('Failed to fetch data'));}, 1000);
});// 使用Promise
fetchData.then((data) => {console.log('Data fetched:', data);}).catch((error) => {console.error('Error fetching data:', error);});

Promise链: 按特定顺序执行一系列异步任务的过程称为Promise链。

它涉及将多个.then()方法到Promise上以按特定顺序执行一系列任务。

new Promise(function (resolve, reject) {setTimeout(() => resolve(1), 1000);
}).then(function (result) {console.log(result); // 1return result * 2;}).then(function (result) {console.log(result); // 2return result * 3;}).then(function (result) {console.log(result); // 6return result * 4;});

8. 什么是async/await ?

Async/await是现代方法来处理JavaScript中的异步代码,它提供了更简洁和易读的方式来使用Promise和异步操作,有效避免“回调地狱”,并改善异步代码的整体结构。

在JavaScript中,使用async关键字来定义一个异步函数,它返回一个Promise

在async函数内部,使用await关键字可以暂停函数的执行,直到Promise被解析,从而实现同步代码的效果,同时处理异步操作。

async function fetchData() {try {const data = await fetch('https://example.com/data');const jsonData = await data.json();return jsonData;} catch (error) {throw error;}
}// 使用异步函数
fetchData().then((jsonData) => {// 处理检索到的数据}).catch((error) => {// 处理错误});

在这个例子中,fetchData函数被定义为一个异步函数,它使用await关键字暂停执行并等待fetch和json操作完成,有效地以类似同步代码的方式处理Promise。

9. =运算符有什么区别?

==(松散相等运算符): 该运算符执行类型强制转换,这意味着它会将操作数转换为相同类型后再进行比较。它检查值是否相等而不考虑它们的数据类型。例如,1 == '1' 将返回true,因为JavaScript会将字符串'1'转换为数字后再进行比较。

===(严格相等运算符): 该运算符执行严格比较不进行类型强制转换。它会检查值和数据类型是否都相等。例如,1 === '1' 将返回false,因为数据类型不同(数字和字符串)。

总结起来,==在类型强制转换后检查相等性,而===在检查严格相等性时会考虑值和数据类型。

===语句相比,==的执行会更快。

下面是一些示例,涵盖了上述情况:

0 == false   // true  
0 === false  // false
1 == "1"     // true
1 === "1"    // false
null == undefined // true  
null === undefined // false
'0' == false // true
'0' === false // false
[]==[] 或 []===[] //false,引用内存中的不同对象
{}=={} 或 {}==={} //false,引用内存中的不同对象

10. 在Javascript中创建对象的不同方法?

在JavaScript中,有几种创建对象的方法。 一些常见的对象创建方法包括:

a)对象字面量: 最直接的创建对象的方法是使用对象字面量,在花括号中以逗号分隔的列表定义对象的属性和方法。

let person = {  firstName: 'John',lastName: 'Doe',greet: function() {return 'Hello, ' + this.firstName + ' ' + this.lastName;}
};

b)构造函数: 可以使用构造函数和new关键字创建对象的多个实例。 在构造函数内部,可以将属性和方法分配给this关键字。

function Person(firstName, lastName) {this.firstName = firstName;this.lastName = lastName;this.greet = function() {return 'Hello, ' + this.firstName + ' ' + this.lastName;};
}let person1 = new Person('John', 'Doe');
let person2 = new Person('Jane', 'Smith'); 

c)Object.create(): Object.create()方法允许您使用指定的原型对象创建新对象。 此方法可对新创建对象的原型提供更多控制。

let personProto = {greet: function() {return 'Hello, ' + this.firstName + ' ' + this.lastName;}  
};let person = Object.create(personProto);
person.firstName = 'John'; 
person.lastName = 'Doe';

d)类语法(ES6): 在ES6中,JavaScript支持使用class关键字定义对象的类语法。 这为以更熟悉和更结构化的方式创建对象及定义其属性和方法提供了一种方法。

class Person {constructor(firstName, lastName) {this.firstName = firstName;this.lastName = lastName;}greet() {return 'Hello, ' + this.firstName + ' ' + this.lastName;}
}let person = new Person('John', 'Doe');

e)工厂函数: 工厂函数是返回对象的函数。 此方法允许您封装对象创建过程,并轻松地使用自定义属性创建多个实例。

function createPerson(firstName, lastName) {return {firstName: firstName,lastName: lastName, greet: function() {return 'Hello, ' + this.firstName + ' ' + this.lastName; }};
}let person1 = createPerson('John', 'Doe');
let person2 = createPerson('Jane', 'Smith'); 

f)Object.setPrototypeOf(): Object.setPrototypeOf()方法可用于为指定对象设置原型。 这为在创建对象之后设置对象原型提供了另一种方法。

let personProto = {greet: function() {return 'Hello, ' + this.firstName + ' ' + this.lastName;}
};let person = {};
person.firstName = 'John';
person.lastName = 'Doe';
Object.setPrototypeOf(person, personProto);

g)Object.assign(): Object.assign()方法可用于通过从一个或多个源对象复制所有可枚举自有属性的值来创建新对象。 这在合并对象或创建浅表副本时特别有用。

let target = { a: 1, b: 2 };
let source = { b: 3, c: 4 }; 
let mergedObject = Object.assign({}, target, source);

h)原型继承: JavaScript使用原型继承,允许对象从其他对象继承属性和方法。 您可以通过利用原型继承并使用构造函数或类的prototype属性来定义共享行为来创建对象。

function Animal(name) {this.name = name; 
}Animal.prototype.greet = function() {return 'Hello, I am ' + this.name;
};function Dog(name, breed) {Animal.call(this, name);this.breed = breed;
}Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;let myDog = new Dog('Max', 'Poodle');

i)单例模式: 单例模式用于将对象限制为单个实例。 它可以通过闭包和立即调用的函数表达式(IIFE)的组合在JavaScript中实现。 这可确保只创建对象的一个实例。

let singleton = (() => {let instance;function createInstance() {return {// properties and methods};}return {getInstance: () => {if (!instance) {instance = createInstance();}return instance;}    };
})();

11. 什么是rest和spread运算符?

rest运算符,表示为三个点(...),用于在函数参数中收集可变数量的参数到一个数组中。 它允许您将任意数量的参数传递给函数,而不需要将它们显式定义为命名参数。

function sum(...numbers) {return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 输出 10

spread运算符,也表示为三个点(...),用于将数组或对象的元素展开到另一个数组或对象中。 它允许您轻松克隆数组、连接数组和合并对象。

const array1 = [1, 2, 3]; 
const array2 = [4, 5, 6];
const mergedArray = [...array1, ...array2];
// mergedArray 是 [1, 2, 3, 4, 5, 6]
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const mergedObject = { ...obj1, ...obj2 };
// mergedObject 是 { a: 1, b: 3, c: 4 }

12. 什么是高阶函数?

JavaScript中的高阶函数是一个函数,它要么接受一个或多个函数作为参数,要么返回一个函数作为其结果。换句话说,它对函数进行操作,无论是将它们作为参数,返回它们还是两者兼有。

function operationOnArray(arr, operation) {let result = [];for (let element of arr) {result.push(operation(element));  }return result; 
}function double(x) {return x * 2;  
}let numbers = [1, 2, 3, 4];
let doubledNumbers = operationOnArray(numbers, double);  
console.log(doubledNumbers); // 输出:[2, 4, 6, 8]

它们支持函数组合、柯里化和基于回调的异步操作等强大技术。理解高阶函数对于编写表达性强和函数式的JavaScript代码至关重要。

一元函数(即单参数函数)是一个只接受一个参数的函数。 它代表一个函数接受的单个参数。

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

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

相关文章

NAND Separate Command Address (SCA) 接口数据传输解读

在采用Separate Command Address (SCA) 接口的存储产品中,DQ input burst和DQ output burst又是什么样的策略呢? DQ Input Burst: 在读取操作期间,数据以一种快速并行的方式通过DQ总线传送到控制器。在SCA接口下,虽然命令和地址信…

关于Python里xlwings库对Excel表格的操作(三十一)

这篇小笔记主要记录如何【如何使用“Chart类”、“Api类"和“Axes函数”设置绘图区外框线型、颜色、粗细及填充颜色】。前面的小笔记已整理成目录,可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 (1)如何安…

【附源码】基于SSM+Java的题库管理系统的设计与实现

基于SSMJava的题库管理系统的设计与实现 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(We…

JAVA序列化

对象序列化(object serialization)是java支持的通用机制,可以将任何对象写出到流中,并在之后将其回读。简单来说,就是可以将对象数据保存为文件,甚至可以通过网络传输,在这之后或者别的主机上恢…

企业如何开展百科营销?需要创建哪些百科词条?

在营销工作实践中,小马识途营销顾问经常接到关于百科营销的咨询,现整理了最受关注的九个问题分享给热爱营销工作的小伙伴。 一、什么是百科营销? 百科营销是借助百科知识传播,可以将企业、品牌、人物所拥有的对用户有价值的信息&a…

Redis的优化

1 Redis的高可用 1.1 高可用的定义 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中,高可用的含义似乎要宽泛一些&…

RTSP网络视频协议

一.RTSP网络视频协议介绍 RTSP是类似HTTP的应用层协议,一个典型的流媒体框架网络体系可参考下图,其中rtsp主要用于控制命令,rtcp主要用于视频质量的反馈,rtp用于视频、音频流从传输。 1、RTSP(Real Time Streaming P…

【群晖NAS】记一次FRP报错:login to server failed: connection write timeout

报错如下: rongfuDS224plus:~/fff/frp$ ./frpc -c ./frpc.toml 2024/01/12 23:08:31 [I] [root.go:139] start frpc service for config file [./frpc.toml] 2024/01/12 23:08:41 [W] [service.go:131] login to server failed: i/o deadline reached 2024/01/12 2…

人工智能:未来智慧城市建设的“智慧大脑”与核心价值

目录 一、引言 二、人工智能在智慧城市中的应用实例 三、人工智能对智慧城市建设的核心价值 四、面临的挑战与未来展望 五、结语 六、附:智慧城市全套解决方案大合集 - 下载 一、引言 随着科技的飞速发展,智慧城市的概念逐渐深入人心。智慧城市利…

70、C++ - 仓库目录结构介绍

如上文所说,后面的优化基本都是基于 C++ 版本的代码来进行的,如果没有 C++ 的编程经验,可以顺便依托这个小的 C++ 项目来学一些 C++ 的基础知识。 后面涉及 C++ 部分的内容,我也会尽可能写的详细一些。 在进行 C++ 部分之前,先介绍一下 C++ 的代码仓库。 仓库链接还是在…

python爬虫实战(10)--获取本站热榜

1. 需要的类库 import requests import pandas as pd2. 分析 通过分析,本站的热榜数据可以直接通过接口拿到,故不需要解析标签,请求热榜数据接口 url "https://xxxt/xxxx/web/blog/hot-rank?page0&pageSize25&type" #本…

最全Linux驱动开发全流程详细解析(持续更新)

Linux驱动开发详细解析 一、驱动概念 驱动与底层硬件直接打交道,充当了硬件与应用软件中间的桥梁。 具体任务 读写设备寄存器(实现控制的方式)完成设备的轮询、中断处理、DMA通信(CPU与外设通信的方式)进行物理内存…

vim文本编辑器,常用命令

目录 1、常用模式 2、基本移动光标 3、插入和替换文本 4、删除和复制文本 5、搜索和替换 6、保存和退出 Vim是一款功能强大的文本编辑器,在Linux系统中被广泛使用。它提供了丰富的编辑和操作功能,适用于编程、文件编辑、配置文件修改等各种任务。 …

linux创建文件并分配权限

linux中对文件的定义 在Linux中,文件是一个具有符号名字的一组相关联元素的有序序列。文件可以包含的内容十分广泛,操作系统和用户都可以将具有一定独立功能的一个程序模块、一组数据或一组文字命名为一个文件。文件名是数据有序序列集合(文…

聚焦老年生活与健康,“老有所依·情暖夕阳”元岗街社区微型养老博览会顺利开展

尊老敬老是中华民族的传统美德, 爱老助老是全社会的共同责任。 家有一老,如有一宝, 长者的生活情况是一个家庭的头等大事, 做好长者服务是街道和社区的重要工作。 2024年1月6日,由元岗街道党工委、元岗街道办事处、…

开源C语言库Melon:红黑树

本文对Melon库中的红黑树进行介绍,关于Melon库,这是一个开源的C语言库,它具有:开箱即用、无第三方依赖、安装部署简单、中英文文档齐全等优势。 Github repo 简介 红黑树是一种被应用的非常广泛的数据结构,用于快速搜…

MySQL 8.0中新增的功能(五)

改进哈希连接性能 MySQL 8.0.23重新实现了用于哈希连接的哈希表,从而改进了哈希连接的性能。这项工作包括修复了一个问题(Bug#31516149,Bug#99933),在这个问题中,用于连接缓冲区&am…

PyQt5系列之核心模块与控件

一、模块介绍 1、QtCore:包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用 2、QtGui:包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类 3、QtWidgets:包含了一些列创建桌面应用的UI元素 二、QtWidgets使用介…

真正的强大,原来是不动声色的

当一个人走过了绝境,他就会发现,真正的强大,原来是不动声色的。 他会停止一切自证,不再解释,话越来越少,眼神越来越坚定。 他不再模棱两可,唯唯诺诺,而是敢于断然拒绝,…

Veeam Backup12安装备份恢复ESXI7.0 U3虚拟机

介绍 只需单个平台即可保护并管理所有工作负载、应用及数据:云端、虚拟、物理、SaaS、Kubernetes、VMware、Hyper-V、Windows、Linux、UNIX、NAS、AWS、Azure、企业应用等。 个人主要用于备份ESXi上的虚拟机,可以实现单次完整备份,和定时的…