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

前端开发面试题总结-JavaScript篇(一)

文章目录

  • JavaScript高频问答
    • 一、作用域与闭包
      • 1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?
      • 2.解释 JavaScript 的作用域链(Scope Chain)
    • 二、原型与继承
      • 3.原型链是什么?如何实现继承?
      • 4.typeof 返回的数据类型
      • 5.typeof 和 instanceof 的区别
      • 6.instanceof 的原理是什么?
    • 三、异步与事件循环
      • 7.解释事件循环(Event Loop)和宏任务/微任务
      • 8.Promise 和 async/await 的区别
    • 四、ES6+ 特性
      • 9.let、const 和 var 的区别
      • 10.箭头函数与普通函数的区别
    • 五、高频手写代码题
      • 11.手写防抖(Debounce)和节流(Throttle)
      • 12.手写深拷贝(Deep Clone)
    • 六、性能优化
      • 13.如何避免 JavaScript 中的内存泄漏?
      • 14.JavaScript 的垃圾回收机制是什么?常见算法有哪些?

JavaScript高频问答

一、作用域与闭包

1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?

● 为什么⾯试官喜欢问闭包?
在 JavaScript 中,闭包(closure)是⼀个重要的概念。它不仅是理解 JavaScript 作⽤域和作⽤域链的 关键,还是实现⼀些⾼级特性和设计模式的基础。
● 什么是闭包?
闭包是指⼀个函数能够访问并操作其⽗函数作⽤域中的变量,即使该⽗函数已经执⾏完毕,离开了执⾏ 环境。在 JavaScript 中,函数内部定义的函数,由于作⽤域链的关系,可以形成闭包。
● 使⽤场景
封装变量, 闭包可以⽤来封装变量,使其不受外界的⼲扰,同时⼜可以通过返回的函数来访问和操作这些变量

function createCounter() {let count = 0;return function() {return ++count;};}const counter = createCounter();
console.log(counter()); // 输出: 1
console.log(counter()); // 输出: 

在上述例⼦中,我们通过 createCounter 函数创建了⼀个计数器,并返回了⼀个闭包函数。这个闭包函数 可以访问和操作 count 变量,⽽ count 变量是被封装的,外界⽆法直接访问。

模块化开发, 闭包在模块化开发中发挥了重要的作⽤。通过闭包,我们可以创建私有变量和⽅法,避免全局命名冲突 和变量污染。

 const module = (function() {let privateVariable = 1;function privateMethod() {console.log('私有⽅法');}return {publicMethod: function() {console.log('公开⽅法');}};})();module.publicMethod(); // 输出: 公开⽅法
module.privateMethod(); // 输出: Uncaught TypeError: module.privateMethod is not a function

在这个例⼦中,我们使⽤⽴即执⾏函数创建了⼀个匿名的函数作⽤域,并返回了⼀个具有公开⽅法的对 象。在函数作⽤域内定义的 privateVariable 和 privateMethod 是私有的,外界⽆法直接访问。

实现缓存 闭包可以⽤于实现数据缓存,特别是在频繁调⽤的情况下提⾼性能

function createCache() {const cache = {};return function(key, value) {if (typeof value !== 'undefined') { // 设置缓存cache[key] = value;} else { // 获取缓存return cache[key];}};
}
const cache = createCache();
cache('name', 'Tom'); // 设置缓存
console.log(cache('name')); // 输出: Tom

在这个例⼦中,我们通过 createCache 函数创建了⼀个⽤于缓存数据的闭包函数。当使⽤闭包函数设置缓 存时,将数据存储在 cache 对象中。当使⽤闭包函数获取缓存时,从 cache 对象中查找并返回数据。

实现私有方法 对于⾯向对象编程来说,私有⽅法是⼀种封装数据和⾏为的重要⽅式,可以防⽌外部直接访问和修改内 部状态。闭包可以帮助我们实现私有⽅法

 function createPerson(name) {const greeting = 'Hello, ' + name;return {sayHello: function() {console.log(greeting);}};}const person = createPerson('Tom');person.sayHello(); // 输出: Hello, Tomperson.greeting; // undefined

在这个例⼦中,我们通过 问和操作 createPerson 函数创建了⼀个对象,其中包含⼀个闭包函数 greeting 变量。外界⽆法直接访问 sayHello,它可以访 greeting 变量,从⽽确保了数据的私有性。

事件处理 闭包在事件处理中⾮常常⻅,特别是在循环或定时器等异步操作中。使⽤闭包可以保存循环变量或定时 器的参数,并确保在回调函数执⾏时以正确的值进⾏处理。例如:

for (var i = 0; i < 5; i++) {(function(index) {setTimeout(function() {console.log(index);}, 1000);})(i);}

在这个例⼦中,我们使⽤⽴即执⾏函数创建了⼀个新的函数作⽤域,每次循环都将 i 的值传递给⽴即执 ⾏函数的参数 index,从⽽在定时器回调函数执⾏时正确地打印每次循环的值。

实现回调函数 闭包在处理回调函数时⾮常有⽤,特别是在处理异步操作的结果或处理事件的响应时。闭包能够保存局 部变量和状态,并在回调函数被调⽤时使⽤。例如:

function fetchData(url, callback) {// 发送⽹络请求获取数据setTimeout(function() {const data = 'Some data';callback(data);}, 2000);}fetchData('https://example.com', function(data) {console.log(data););

在这个例⼦中,我们定义了⼀个 JavaScript fetchData 函数⽤于异步获取数据。在获取到数据后,通过闭包将数据传 递给回调函数并执⾏回调函数,从⽽实现对数据的处理和使⽤。

实现递归 闭包在递归算法中经常被使⽤,可以保存递归中的状态和结果,并确保在每次递归调⽤时使⽤正确的 值。例如 :

function factorial(n) {if (n === 1) {return 1;} else {return n * factorial(n - 1);}}console.log(factorial(5)); // 输出: 120

在这个例⼦中, factorial 函数使⽤递归的⽅式计算阶乘。在每次递归调⽤时,通过闭包保存当前的状态和 结果,并随着递归的进⾏传递给下⼀次的递归调⽤。

闭包在 JavaScript 中具有重要的意义,除了以上的⼏个场景之外, 它还可以解决函数柯⾥化和迭代器以 及链式调⽤等其他问题。掌握闭包的概念和使⽤场景,对于编写⾼效、安全的 JavaScript 代码⾮常有帮助

2.解释 JavaScript 的作用域链(Scope Chain)

作用域链是变量查找的机制。函数执行时,会先从当前作用域查找变量,如果找不到则向外层作用域逐级查找,直到全局作用域。作用域链在函数定义时确定,与调用位置无关(词法作用域)。

  let num1 = 100function sum(){let num2 = 200function sum2(){console.log(num1)}sum2()}sum()

二、原型与继承

3.原型链是什么?如何实现继承?

● 原型链:每个对象都有一个 __proto__ 属性指向其构造函数的原型对象(prototype),形成链式结构,实现属性和方法的继承。
在这里插入图片描述
实现继承(ES5):
○ 原型链继承
○ 构造函数继承
○ 组合式继承
○ 原型式继承
○ 寄生式继承
○寄生组合式继承

function Parent(name) { this.name = name; }
Parent.prototype.say = function() { console.log(this.name); };
function Child(name) { Parent.call(this, name); }
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

ES6+
class类结合extends和super函数实现继承

4.typeof 返回的数据类型

typeof 适合检测简单数据类型和函数,但对引用类型(如数组、对象)区分能力有限,需结合其他方法(如 instanceof、Array.isArray())使用。

5.typeof 和 instanceof 的区别

● typeof:检测基本数据类型(返回类型字符串,如 "number"、"string")。
● instanceof:检测引用类型(判断对象是否是某个构造函数的实例,如 [] instanceof Array → true)。
● 适用场景:
○ typeof:快速判断基本类型或检查变量是否定义。
○ instanceof:确认对象的具体类型(如数组、自定义类)。

6.instanceof 的原理是什么?

typeOf只能判断简单数据的数据类型, 如果要去判断复杂数据的数据类型则用instanceof, 原理如下:
instanceof 通过检查对象的原型链中是否存在构造函数的 prototype 属性:

function myInstanceof(obj, Constructor) {let proto = obj.__proto__;while (proto) {if (proto === Constructor.prototype) return true;proto = proto.__proto__;}return false;
}

三、异步与事件循环

7.解释事件循环(Event Loop)和宏任务/微任务

● 事件循环:JavaScript 是单线程的, 需要结合事件循环去处理异步,代码在执行之前会有预解析, 把同步代码放在主线程, 把异步代码放在事件循环;
● 事件调用又分为调用栈、任务队列(宏任务队列和微任务队列)。
● 执行顺序:同步代码 → 微任务(如 Promise.then)→ 宏任务(如 setTimeout)。

console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
// 输出顺序:1 → 4 → 3 → 2

8.Promise 和 async/await 的区别

● Promise:通过链式调用 .then 处理异步,解决回调地狱,但嵌套多时仍不够直观。
○ 常用的静态方法: Promise.all(), Promise.race(), Promise.resolve(), Promise.reject(), Promise.allSettled()…
● async/await:基于 Promise 的语法糖,用同步写法处理异步,更易读。

async function fetchData() {try {const res = await fetch('url');const data = await res.json();} catch (error) {console.error(error);}
}

四、ES6+ 特性

9.let、const 和 var 的区别

答案:
● var:函数作用域,存在变量提升(声明前访问为 undefined)。
● let/const:块级作用域,不存在变量提升,存在暂时性死区(声明前访问报错)。
● const:声明常量,赋值后不可修改(对象属性可修改, 数组的内容可修改)。

// 1. var存在变量提升
var dog
console.log(dog)
console.log('666')
// var dog = '旺财'
dog = '旺财'

10.箭头函数与普通函数的区别

答案:
● 箭头函数没有自己的 this,继承外层作用域的 this。
● 不能用作构造函数(无法 new)。
● 没有 arguments 对象,可用剩余参数(…args)替代。
● 箭头函数没有prototype, 普通函数具备prototype。

// 1. 不能用作构造函数
// 正确的
function Person(){}
new Person()
// 错误的
const Dog = ()=>{}
new Dog()// 2. 没有 arguments 对象
function sum(num1, num2){// 函数内置的一个对象// 用于存放调用函数时传入的所有实参console.log(arguments)
}
sum(100, 200)// 报错: arguments is not defined
const sum1 = (num1)=>{console.log(arguments)
}
sum1(100)

五、高频手写代码题

11.手写防抖(Debounce)和节流(Throttle)

// 防抖:多次触发后只执行一次
// 使用场景: 搜索框
function debounce(fn, delay) {let timer;return function(...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
}// 节流:固定时间内只执行一次
// 使用场景: scroll滚动, resize可视区域变化
function throttle(fn, delay) {let last = 0;return function(...args) {const now = Date.now();if (now - last >= delay) {fn.apply(this, args);last = now;}};
}

12.手写深拷贝(Deep Clone)

function deepClone(obj, map = new Map()) {if (typeof obj !== 'object' || obj === null) return obj;if (map.has(obj)) return map.get(obj); // 解决循环引用const clone = Array.isArray(obj) ? [] : {};map.set(obj, clone);for (const key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key], map);}}return clone;
}

六、性能优化

13.如何避免 JavaScript 中的内存泄漏?

答案:
● 常见原因:
a. 未清理的全局变量、定时器或事件监听。
b. 闭包中意外保留的大对象。
c. DOM 引用未释放(如已移除节点的引用)。
● 解决方法:
○ 使用 let/const 替代 var,减少全局变量。
○ 及时清除定时器(clearTimeout)、事件监听(removeEventListener)。
○ 使用弱引用(WeakMap/WeakSet)管理对象。

14.JavaScript 的垃圾回收机制是什么?常见算法有哪些?

答案:
● 机制:自动回收不再使用的内存,防止内存泄漏。
● 常见算法:
○ 标记清除(Mark-Sweep):标记所有可达对象,清除未标记的对象(主流浏览器使用)。
○ 引用计数(Reference Counting):记录对象被引用次数,归零时回收(无法处理循环引用,已淘汰)。
○ 分代回收(Generational Collection):V8 引擎将内存分为新生代(短生命周期)和老生代(长生命周期),分别使用 Scavenge 和标记清除/整理算法。

相关文章:

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...