1. JS有哪些数据类型,它们的区别有哪些?
JS 数据类型分为基本数据类型和引用数据类型。
• 基本数据类型:String、Number、Boolean、Null、Undefined、Symbol、BigInt,共7种,存储在栈内存,值不可变,按值传递。
• 引用数据类型:Object(包含Array、Function、Date等),存储在堆内存,栈内存保存堆内存地址,值可变,按引用传递。
2. 数据类型检测的方式有哪些?
1. typeof:检测基本数据类型(null 会被识别为 object),引用类型除 function 外都识别为 object。
2. instanceof:检测构造函数的 prototype 是否出现在实例的原型链上,适用于引用类型。
3. Object.prototype.toString.call() :最准确的检测方式,返回 [object 类型] 格式字符串,可识别所有数据类型。
4. constructor:通过实例的 constructor 属性指向其构造函数来判断。
3. 介绍下Ajax
Ajax 全称 Asynchronous JavaScript and XML(异步 JavaScript 和 XML),是一种在不重新加载整个页面的情况下,与服务器交换数据并更新部分页面的技术。核心是 XMLHttpRequest 对象(或现代的 fetch API),实现异步请求,提升用户体验。流程:创建请求对象→配置请求参数→发送请求→监听状态变化→处理响应数据。
4. 如何判断一个数据是NaN?
5. Number.isNaN():ES6 新增方法,仅当参数是 NaN 且类型为 Number 时返回 true,避免了全局 isNaN() 的类型转换问题。
6. value !== value:利用 NaN 是唯一不等于自身的值的特性,这是判断 NaN 的可靠方法。
5. null和undefined的区别
• undefined:表示变量已声明但未赋值,或对象属性不存在,是 JS 自动赋予的初始值;typeof undefined 返回 undefined。
• null:表示变量主动赋值为“空值”,代表一个空对象指针;typeof null 返回 object。
• 转换为数值时:Number(undefined) 是 NaN,Number(null) 是 0。
6. 介绍下闭包,在什么场景下使用过?
• 定义:闭包是指有权访问另一个函数作用域中变量的函数,本质是函数作用域链的保留。
• 特性:延长外部函数变量的生命周期,隔离作用域避免变量污染。
• 使用场景:① 封装私有变量(如计数器函数,避免全局变量);② 防抖节流函数的实现;③ 模块化开发中暴露特定方法。
7. 事件委托是什么?如何确定事件源?
• 事件委托:利用事件冒泡机制,将子元素的事件绑定到父元素上,由父元素统一处理。优点是减少事件绑定次数、支持动态添加的子元素。
• 确定事件源:在事件处理函数中,通过 event.target(触发事件的真实元素)获取事件源,兼容低版本 IE 用 event.srcElement。
8. 本地存储与cookie的区别
| 特性 | 本地存储(localStorage/sessionStorage) | Cookie |
|---|---|---|
| 存储大小 | 约 5MB | 约 4KB |
| 生命周期 | localStorage 永久存储,sessionStorage 会话结束失效 | 可设置过期时间,默认会话结束失效 |
| 与服务器交互 | 不随请求发送到服务器 | 每次请求自动携带到服务器 |
| 作用域 | 同源页面共享 | 同源且符合路径、域名规则 |
9. 简述下ES6的新特性
7. 块级作用域:let、const 关键字。
8. 箭头函数:简化函数写法,无自己的 this。
9. 解构赋值:快速提取数组、对象的属性。
-
模板字符串:反引号 ` 包裹,支持换行和变量插值 ${}。
-
类与继承:class、extends 关键字,简化原型链写法。
-
模块化:import/export 语法。
-
新增数据结构:Set、Map。
-
异步方案:Promise 对象。
-
其他:默认参数、剩余参数 ...、扩展运算符 ... 等。
10. Let、var和const的区别
| 特性 | var | let | const |
|---|---|---|---|
| 作用域 | 函数作用域/全局作用域 | 块级作用域 | 块级作用域 |
| 变量提升 | 存在,可先使用后声明 | 存在暂时性死区,不可先使用 | 同 let |
| 重复声明 | 允许 | 不允许 | 不允许 |
| 赋值 | 可多次赋值 | 可多次赋值 | 声明时必须赋值,且不可修改引用(基本类型不可改,引用类型属性可改) |
11. 数组都有哪些方法
-
增删改查:push()(尾增)、pop()(尾删)、unshift()(头增)、shift()(头删)、splice()(增删改)、slice()(截取)。
-
遍历迭代:forEach()、map()、filter()、reduce()、some()、every()。
-
排序与转换:sort()(排序)、reverse()(反转)、join()(转字符串)、concat()(合并数组)。
-
其他:indexOf()/lastIndexOf()(查找索引)、includes()(判断是否包含)、find()/findIndex()(查找元素/索引)、flat()(扁平化数组)。
12. JSON如何新增和删除键值对
JSON 本质是符合格式的 JS 对象,操作方式与对象一致:
• 新增键值对:obj.key = value 或 obj['key'] = value。
• 删除键值对:使用 delete obj.key 或 delete obj['key']。
13. 简述下面向对象
面向对象(OOP)是一种编程思想,核心是封装、继承、多态。
• 封装:将数据和操作数据的方法封装在对象中,隐藏内部细节,暴露公共接口。
• 继承:子类继承父类的属性和方法,实现代码复用。
• 多态:同一方法在不同对象上有不同的表现形式(JS 中通过重写方法实现)。
JS 是基于原型的面向对象语言,没有类的概念(ES6 class 是语法糖)。
14. 普通函数与构造函数的区别
• 命名规范:构造函数首字母通常大写,普通函数首字母小写。
• 调用方式:构造函数用 new 关键字调用,普通函数直接调用。
• 返回值:构造函数默认返回实例对象(手动返回对象会覆盖);普通函数无 return 时返回 undefined。
• this ****指向:构造函数中 this 指向新创建的实例;普通函数中 this 指向调用者(全局调用指向 window/global)。
15. 请简述原型,原型链和继承
• 原型(prototype ) :每个函数都有 prototype 属性,指向原型对象,原型对象包含所有实例共享的属性和方法。
• 原型链:每个实例对象都有 proto 属性,指向其构造函数的 prototype;当访问实例属性时,会依次向上查找原型对象,直到 Object.prototype,这条链式结构就是原型链。
• 继承:JS 中继承基于原型链实现,子类实例的 proto 指向父类的 prototype,从而继承父类的属性和方法;常见方式有原型链继承、构造函数继承、组合继承等。
16. 简述下对Promise的理解以及你在什么情况下使用过
• Promise 理解:Promise 是解决 JS 异步回调地狱的方案,代表一个异步操作的最终完成(或失败)及其结果值。有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败),状态一旦改变不可逆转。提供 then()、catch()、finally() 方法链式调用。
• 使用场景:① 异步请求(如 axios 基于 Promise 封装,处理接口请求的成功和失败);② 读取文件(Node.js 中 fs.promises 模块);③ 多个异步操作的串行/并行处理(Promise.all()/Promise.race())。
17. 简述下async的用法
async 用于声明异步函数,返回值是一个 Promise 对象;await 关键字只能在 async 函数中使用,用于等待 Promise 执行完成,暂停函数执行直到 Promise 状态变为 fulfilled 或 rejected。
• 成功时:await 返回 Promise 的成功值;
• 失败时:需用 try/catch 捕获异常,否则会抛出错误。
• 作用:将异步代码以同步的写法呈现,比 Promise 链式调用更简洁。
18. 简述下jQuery
jQuery 是一款轻量级的 JS 库,核心思想是 Write Less, Do More(写得更少,做得更多)。它封装了原生 JS 的 DOM 操作、事件处理、Ajax 请求等功能,解决了浏览器兼容性问题。特点:① 简洁的选择器;② 链式调用;③ 丰富的插件生态;④ 动画效果便捷。但随着 Vue、React 等框架的兴起,jQuery 在现代前端开发中使用逐渐减少。
19. 什么是Sass、Less,为什么使用它们
• Sass/Less:都是 CSS 预处理器,扩展了 CSS 的语法,增加了变量、混合、嵌套、继承等特性,让 CSS 更易维护和复用。Sass 后缀是 .scss(或 .sass),Less 后缀是 .less。
• 使用原因:① 变量:统一管理颜色、字体等样式属性;② 嵌套:模拟 DOM 层级结构,增强代码可读性;③ 混合:复用公共样式片段;④ 继承:减少代码冗余;⑤ 模块化:拆分样式文件,便于维护。
20. JS中call()和apply()方法的区别
call() 和 apply() 都用于改变函数执行时 this 的指向,第一个参数都是 this 要指向的对象。
• 区别:传入参数的方式不同。
◦ call():第一个参数是 this 指向,后续参数是单个参数列表,用逗号分隔。
例:fn.call(obj, arg1, arg2)
◦ apply():第一个参数是 this 指向,第二个参数是参数数组(或类数组对象)。
例:fn.apply(obj, [arg1, arg2])
21. 为什么会造成跨域?
跨域是指浏览器的同源策略限制,当一个请求的协议、域名、端口三者中任意一个与当前页面不同,就会产生跨域。同源策略是浏览器的安全机制,防止不同源的页面之间随意访问数据,避免 XSS、CSRF 等攻击。
22. this有几种指向?
-
全局环境:this 指向全局对象(浏览器中是 window,Node.js 中是 global)。
-
函数直接调用:非严格模式下 this 指向全局对象,严格模式下 this 是 undefined。
-
对象方法调用:this 指向调用该方法的对象。
-
构造函数调用:this 指向新创建的实例对象。
-
call() / apply() / bind() ****调用:this 指向传入的第一个参数。
-
箭头函数:没有自己的 this,this 指向箭头函数定义时所在作用域的 this。
-
事件处理函数:this 指向触发事件的 DOM 元素。
23. 请说出三种减少页面加载时间的方式
-
资源压缩:压缩 JS、CSS、HTML 文件,减小文件体积;压缩图片(WebP 格式、图片压缩工具)。
-
资源缓存:设置合理的 HTTP 缓存头(如 Cache-Control、Expires),利用 localStorage 缓存不常变化的静态资源。
-
减少 HTTP 请求:合并 CSS/JS 文件,使用雪碧图合并小图标,采用懒加载加载非首屏资源。
-
CDN 加速:将静态资源部署到 CDN 服务器,就近获取资源,提高加载速度。
24. 什么是JSONP,工作原理是什么?它为什么不是真正的Ajax?
• JSONP:是一种跨域请求解决方案,全称 JSON with Padding。
• 工作原理:利用
• 不是真正的 Ajax:Ajax 基于 XMLHttpRequest 对象实现,而 JSONP 基于
25. 说几种数组去重方式
-
利用 Set:[...new Set(arr)],简洁高效,ES6 推荐方法。
-
利用 indexOf/includes:遍历数组,判断元素是否已存在于新数组中,不存在则添加。
-
利用 filter + indexOf:arr.filter((item, index) => arr.indexOf(item) === index)。
-
利用对象属性唯一性:将数组元素作为对象的键,避免重复。
26. 简述下深浅拷贝,并说下如何分别实现,以及使用场景
• 浅拷贝:只复制对象的第一层属性,若属性是引用类型,复制的是地址,修改新对象会影响原对象。
◦ 实现方法:Object.assign()、扩展运算符 {...obj}、数组 slice()/concat()。
◦ 使用场景:复制只有基本类型属性的简单对象。
• 深拷贝:复制对象的所有层级属性,新对象与原对象完全独立,修改互不影响。
◦ 实现方法:JSON.parse(JSON.stringify(obj))(缺点:无法复制函数、RegExp 等)、递归手写深拷贝、lodash.cloneDeep()。
◦ 使用场景:复制包含引用类型属性的复杂对象(如嵌套对象、数组)。
27. 为什么JS是弱类型语言
弱类型语言的特点是变量类型不固定,支持隐式类型转换。JS 中变量声明时不需要指定类型,赋值后类型可以随时改变;在运算时,JS 会自动将不同类型的值转换为相同类型再计算(如 1 + '2' = '12')。与之相对的是强类型语言(如 Java),变量类型固定,必须显式转换类型。
28. 怎么转换Less为CSS
-
使用 Less 官方编译器:安装 Node.js 后,通过 npm 安装 less 包,执行命令 lessc styles.less styles.css 编译。
-
构建工具集成:在 Webpack/Vite 等构建工具中配置 less-loader,打包时自动将 Less 转换为 CSS。
-
编辑器插件:使用 VS Code 的 Easy LESS 插件,保存 Less 文件时自动生成对应的 CSS 文件。
29. ECharts使用最多的是什么?
ECharts 是百度开源的可视化图表库,使用最多的是各类统计图表的绘制,包括:
-
折线图/ 柱状图:用于展示数据的趋势和对比。
-
饼图/ 环形图:用于展示数据的占比情况。
-
地图:用于展示地理相关的数据分布。
-
仪表盘:用于展示关键指标的数值。
核心是通过配置项 option 设置图表的数据源、样式、交互等属性。
30. for循环和map循环有什么区别?
-
返回值:for 循环无返回值,需手动操作数组;map 循环返回一个新数组,新数组元素是原数组元素经过回调函数处理后的结果。
-
功能:for 循环可用于遍历、修改原数组、跳出循环(break/continue);map 循环主要用于映射转换数组,不能中断循环。
-
可读性:map 循环写法更简洁,语义化更强,适合数组的批量转换;for 循环更灵活,适合复杂的遍历逻辑。
31. 请写一个简单的类与继承
// 父类class Person { constructor(name, age) { this.name = name; this.age = age; } sayHello() { console.log(我是${this.name},今年${this.age}岁); }}// 子类继承父类class Student extends Person { constructor(name, age, grade) { super(name, age); // 调用父类构造函数 this.grade = grade; } study() { console.log(${this.name}在${this.grade}年级学习); }}// 实例化const stu = new Student('小明', 12, 6);stu.sayHello(); // 我是小明,今年12岁stu.study(); // 小明在6年级学习 |
|---|
32. 同步与异步的区别?阻塞与非阻塞的区别?
同步与异步
• 同步:代码按顺序执行,前一个任务完成后才执行下一个任务,主线程会被阻塞。例:普通函数调用、alert()。
• 异步:任务不会阻塞主线程,发起后继续执行后续代码,任务完成后通过回调/事件通知结果。例:setTimeout、Ajax 请求。
阻塞与非阻塞
• 阻塞:线程执行任务时,必须等待任务完成才能继续执行其他操作,线程处于等待状态。
• 非阻塞:线程执行任务时,若任务未完成,可立即返回去执行其他操作,无需等待,通过轮询或回调获取任务结果。
• 关系:同步≠阻塞,异步≠非阻塞,它们是不同维度的概念(同步异步描述任务的执行顺序,阻塞非阻塞描述线程的状态)。
33. HTTP是什么?有什么特点?
HTTP 全称 HyperText Transfer Protocol(超文本传输协议),是用于在客户端和服务器之间传输数据的应用层协议,基于 TCP/IP 协议。
• 特点:
a. 无状态:协议本身不记录客户端的请求状态,每次请求都是独立的(可通过 Cookie/Session 保持状态)。
b. 无连接:HTTP 1.0 中,每次请求都要建立新的 TCP 连接,请求完成后断开;HTTP 1.1 支持持久连接(Keep-Alive)。
c. 简单快速:请求格式简单,客户端向服务器发送请求方法和路径,服务器返回状态码和数据。
d. 灵活:支持多种数据类型(如文本、图片、视频等)。
34. HTTP协议和HTTPS的区别
| 特性 | HTTP | HTTPS |
|---|---|---|
| 安全性 | 明文传输,数据易被窃取、篡改 | 加密传输(SSL/TLS 协议),数据安全 |
| 端口 | 默认 80 | 默认 443 |
| 证书 | 无需证书 | 需要 CA 颁发的 SSL 证书 |
| 性能 | 速度快,无加密解密开销 | 速度稍慢,有加密解密过程 |
| 资源消耗 | 低 | 高 |
35. 原型和继承,prototype,call和apply继承的区别
• 原型继承:将子类的 prototype 指向父类的实例,子类实例可继承父类原型上的属性和方法。缺点:父类的引用类型属性会被所有子类实例共享;无法向父类构造函数传参。
• call/apply 继承:在子类构造函数中调用父类构造函数,通过 call()/apply() 改变父类 this 指向子类实例,实现父类实例属性的继承。缺点:无法继承父类原型上的方法。
• 组合继承:结合原型继承和 call/apply 继承,既继承父类实例属性,又继承父类原型方法,是最常用的继承方式。
36. 说几种数组和字符串的方法及他们的作用
数组方法
-
map():遍历数组,返回新数组,元素为回调函数处理结果。
-
filter():过滤数组元素,返回符合条件的新数组。
-
reduce():累计计算数组元素,返回最终结果(如求和、求积)。
-
find():返回数组中第一个符合条件的元素。
字符串方法
-
split():将字符串按分隔符分割为数组。
-
indexOf()/includes():查找子字符串是否存在,返回索引或布尔值。
-
substring()/slice():截取字符串的指定部分。
-
replace():替换字符串中的指定内容。
37. 箭头函数与普通函数的区别
-
this ****指向:箭头函数无自己的 this,指向定义时所在作用域的 this;普通函数 this 指向调用者。
-
构造函数:箭头函数不能作为构造函数,不能用 new 调用;普通函数可以。
-
参数:箭头函数没有 arguments 对象,可使用剩余参数 ...args;普通函数有 arguments。
-
原型:箭头函数没有 prototype 属性;普通函数有。
-
写法:箭头函数写法更简洁,适合回调函数;普通函数写法更灵活。
38. 什么是JS内存泄露
内存泄露是指程序中已不再使用的内存没有被及时释放,导致内存占用越来越高,最终影响程序性能甚至崩溃。JS 中常见的内存泄露场景:
-
意外的全局变量(如未声明的变量)。
-
闭包导致的变量未释放。
-
未清除的定时器/事件监听器。
-
DOM 元素被删除但仍有引用(如变量保存了已删除的 DOM 节点)。
39. 如何对网站的文件和资源进行优化
-
静态资源优化:压缩 JS/CSS/HTML,图片格式转换(WebP)、图片懒加载、雪碧图合并小图标。
-
资源加载优化:使用 CDN 加速,预加载关键资源(preload),预解析 DNS(dns-prefetch)。
-
代码优化:减少 HTTP 请求,合并文件;删除无用代码(Tree Shaking);延迟加载非首屏脚本。
-
缓存优化:设置强缓存和协商缓存,利用 localStorage 缓存静态数据。
-
服务器优化:启用 Gzip/Brotli 压缩,使用 HTTP/2 协议(多路复用)。
40. 简述Ajax的执行过程以及常见的HTTP状态码
Ajax 执行过程
-
创建 XMLHttpRequest 对象:const xhr = new XMLHttpRequest()。
-
配置请求参数:xhr.open(method, url, async)(method:请求方法;url:请求地址;async:是否异步)。
-
设置响应处理函数:xhr.onreadystatechange = function() {},监听 readyState 变化。
-
发送请求:xhr.send(data)(POST 请求需传递数据)。
-
处理响应:当 readyState === 4 且 status === 200 时,获取响应数据 xhr.responseText。
常见 HTTP 状态码
• 2xx 成功:200(请求成功)、201(创建资源成功)。
• 3xx 重定向:301(永久重定向)、302(临时重定向)、304(资源未修改,使用缓存)。
• 4xx 客户端错误:400(请求参数错误)、401(未授权)、403(禁止访问)、404(资源不存在)。
• 5xx 服务器错误:500(服务器内部错误)、503(服务器不可用)。
41. 预加载和懒加载的区别,预加载在什么时间合适
区别
• 预加载:提前加载未来可能需要的资源(如图片、JS 文件),加载完成后缓存,当用户需要时直接从缓存读取,提升体验。主动加载,会增加首屏加载时间。
• 懒加载:延迟加载非首屏资源,只有当资源进入可视区域时才加载,减少首屏加载时间,提升页面加载速度。被动加载,适用于图片、视频等大量静态资源。
预加载合适的时间
预加载应在首屏资源加载完成后进行,避免抢占首屏资源的带宽,影响首屏渲染速度。可通过 window.onload 事件触发,或在页面空闲时(requestIdleCallback)执行。
42. jQuery选择器有哪些?
jQuery 选择器基于 CSS 选择器,分为以下几类:
-
基本选择器:ID 选择器(('#id'))、类选择器(('.class'))、标签选择器(('*'))。
-
层级选择器:后代选择器(('parent > child'))、相邻兄弟选择器($('prev + next'))。
-
过滤选择器:基本过滤(:first、:last、:eq(index))、内容过滤(:contains(text))、可见性过滤(:visible、:hidden)。
-
属性选择器:('[attr=value]')。
43. jQuery插入节点的方法
- 内部插入:
◦ append():在元素内部末尾插入节点。
◦ prepend():在元素内部开头插入节点。
- 外部插入:
◦ after():在元素外部后面插入节点。
◦ before():在元素外部前面插入节点。
-
替换节点:replaceWith():用新节点替换原节点。
-
包裹节点:wrap():用指定节点包裹每个匹配元素。
44. Get和Post区别
| 特性 | GET | POST |
|---|---|---|
| 请求参数 | 拼接在 URL 后,可见 | 放在请求体中,不可见 |
| 数据长度 | 受 URL 长度限制,较小 | 无限制,可传输大量数据 |
| 安全性 | 低,参数暴露在 URL | 高,参数隐藏在请求体 |
| 缓存 | 可被浏览器缓存 | 不可被缓存 |
| 幂等性 | 幂等(多次请求结果相同) | 非幂等(多次请求可能产生不同结果) |
| 用途 | 读取数据 | 提交/修改数据 |
45. 什么是CSRF攻击
CSRF 全称 Cross-Site Request Forgery(跨站请求伪造),是一种网络攻击手段。攻击者诱导用户在已登录目标网站的情况下,访问恶意网站,利用用户的登录状态向目标网站发送伪造的请求,从而执行非用户意愿的操作(如转账、修改密码)。防御措施:① 验证 Referer 字段;② 使用 CSRF Token;③ 验证码验证。
46. 如何遍历一个多维数组?
- 递归遍历:遍历数组元素,若元素是数组则递归调用遍历函数,否则处理元素。
| function traverse(arr) { arr.forEach(item => { if (Array.isArray(item)) { traverse(item); } else { console.log(item); } });} |
|---|
- 扁平化后遍历:用 flat() 方法将多维数组扁平化为一维数组,再遍历。
| const arr = [1, [2, [3, 4]]];arr.flat(Infinity).forEach(item => console.log(item)); |
|---|
47. Axios的特性?
Axios 是基于 Promise 的 HTTP 客户端,支持浏览器和 Node.js,核心特性:
-
支持 Promise API,可链式调用。
-
拦截请求和响应(请求拦截器处理 token,响应拦截器统一处理错误)。
-
转换请求和响应数据(如自动转换 JSON 数据)。
-
取消请求。
-
防止 CSRF 攻击。
-
客户端支持防御 XSRF。
-
支持多种请求方法(GET、POST、PUT、DELETE 等)。
48. 在地址栏输入一个URL,到页面呈现出来,中间发生了什么?
-
DNS 解析:将域名转换为对应的 IP 地址。
-
建立 TCP 连接:客户端与服务器通过三次握手建立连接(HTTP/1.1 默认为持久连接)。
-
发送 HTTP 请求:客户端向服务器发送请求行、请求头、请求体。
-
服务器处理请求:服务器解析请求,处理业务逻辑,生成响应数据。
-
服务器返回响应:服务器向客户端发送响应行、响应头、响应体(HTML 等资源)。
-
关闭 TCP 连接:通过四次挥手关闭连接(若开启 Keep-Alive 则保持连接)。
-
浏览器解析渲染页面:
◦ 解析 HTML 生成 DOM 树;
◦ 解析 CSS 生成 CSSOM 树;
◦ 结合 DOM 树和 CSSOM 树生成渲染树;
◦ 布局(Layout):计算元素的位置和大小;
◦ 绘制(Paint):将渲染树绘制到屏幕上。
49. 异步操作的解决方案
-
回调函数:最基础的方案,将异步操作的结果处理逻辑传入回调函数,但容易导致回调地狱。
-
Promise:解决回调地狱,通过 then()/catch() 链式调用,支持多个异步操作的串行/并行处理。
-
async/await:基于 Promise 的语法糖,以同步写法实现异步操作,代码更简洁易读。
-
Generator 函数:通过 yield 暂停函数执行,next() 恢复执行,可实现异步流程控制(较少使用)。
50. map和forEach的区别
| 特性 | map | forEach |
|---|---|---|
| 返回值 | 返回新数组,元素为回调处理结果 | 无返回值(返回 undefined) |
| 功能 | 映射转换数组,适合生成新数组 | 遍历数组,适合执行操作(如打印、修改原数组) |
| 中断循环 | 无法中断,必须遍历所有元素 | 无法中断(无 break/continue) |
| 性能 | 稍慢(需创建新数组) | 稍快(无新数组创建) |
51. TCP和UDP的区别
| 特性 | TCP | UDP |
|---|---|---|
| 连接性 | 面向连接(三次握手建立连接) | 无连接(直接发送数据) |
| 可靠性 | 可靠传输,保证数据有序、不丢失 | 不可靠传输,不保证数据到达 |
| 传输方式 | 流式传输,数据无边界 | 数据包传输,数据有边界 |
| 拥塞控制 | 有拥塞控制和流量控制 | 无拥塞控制 |
| 速度 | 较慢 | 较快 |
| 用途 | 文件传输、网页加载、邮件发送 | 视频直播、语音通话、实时游戏 |
52. BOM和DOM的区别
• DOM:全称 Document Object Model(文档对象模型),是 HTML/XML 文档的编程接口,将文档解析为树形结构,提供操作元素、属性、事件的方法(如 document.getElementById())。核心是 document 对象。
• BOM:全称 Browser Object Model(浏览器对象模型),是与浏览器窗口交互的接口,提供操作浏览器窗口、地址栏、历史记录等的方法(如 window.open()、location.href)。核心是 window 对象,DOM 是 BOM 的一部分。
53. 简述下Git操作
Git 是分布式版本控制系统,常用操作:
-
初始化仓库:git init。
-
克隆仓库:git clone 。
-
文件操作:git add (添加到暂存区)、git commit -m "message"(提交到本地仓库)。
-
分支操作:git branch(查看分支)、git branch (创建分支)、git checkout (切换分支)、git merge (合并分支)。
-
远程操作:git remote add origin (关联远程仓库)、git push -u origin master(推送代码)、git pull(拉取代码)。
-
版本回退:git log(查看提交记录)、git reset --hard (回退到指定版本)。
54. 什么是Node.js?
Node.js 是基于 Chrome V8 引擎的 JavaScript 运行时环境,让 JS 可以脱离浏览器运行在服务器端。特点:
-
非阻塞 I/O:处理高并发请求性能优异。
-
事件驱动:基于事件循环机制,异步处理请求。
-
丰富的模块生态:通过 npm 管理大量第三方模块。
-
跨平台:支持 Windows、Linux、macOS 等系统。
用途:搭建后端服务器、开发 CLI 工具、构建前端工程化工具(如 Webpack)。
55. 遍历数组,遍历对象,遍历字符串的方法都有哪些?哪些可以打断?
遍历数组
-
可打断的方法:for 循环(break/continue)、for...of 循环(break/continue)。
-
不可打断的方法:forEach()、map()、filter()、reduce()。
遍历对象
-
for...in:遍历对象的可枚举属性(包括原型链上的属性),可通过 break 打断。
-
Object.keys()/Object.values()/Object.entries():返回数组后遍历,可结合 for 循环打断。
遍历字符串
-
可打断的方法:for 循环、for...of 循环。
-
不可打断的方法:split('').forEach()。
56. 回流和重绘
• 回流(Reflow ) :当元素的布局属性发生变化(如宽高、位置、DOM 结构),浏览器需要重新计算元素的几何属性和位置,重新构建渲染树,这个过程叫回流。回流代价较高,会触发重绘。
• 重绘(Repaint ) :当元素的样式属性发生变化(如颜色、背景色),但不影响布局时,浏览器只需重新绘制元素外观,这个过程叫重绘。重绘代价低于回流。
• 触发回流的操作:添加/删除 DOM 元素、改变元素尺寸、改变窗口大小、offsetWidth/offsetHeight 等属性的读取。
• 优化:减少回流次数(如批量修改样式、使用 documentFragment 批量添加 DOM)。
57. 节流和防抖
• 防抖(Debounce ) :触发事件后,在指定时间内没有再次触发事件,才执行回调函数;若在指定时间内再次触发,则重新计时。适用于搜索框输入联想、窗口大小调整等场景。
| function debounce(fn, delay) { let timer = null; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); };} |
|---|
• 节流(Throttle ) :触发事件后,每隔指定时间执行一次回调函数,在指定时间内多次触发只执行一次。适用于滚动加载、鼠标移动、按钮点击等场景。
| function throttle(fn, interval) { let lastTime = 0; return function(...args) { const now = Date.now(); if (now - lastTime >= interval) { fn.apply(this, args); lastTime = now; } };} |
|---|
58. 宏任务和微任务
宏任务和微任务是 JS 异步任务的分类,事件循环中执行顺序为:先执行同步代码****→ 执行所有微任务→ 执行一个宏任务→ 再执行所有微任务,以此循环。
• 宏任务(Macrotask ) :执行时间较长的任务,包括 setTimeout、setInterval、I/O、UI 渲染、script 整体代码。
• 微任务(Microtask ) :执行时间较短的任务,包括 Promise.then()/catch()/finally()、async/await、queueMicrotask()、MutationObserver。
59. 什么是装饰器?
装饰器(Decorator)是一种设计模式,用于在不修改原函数/类代码的前提下,动态地为其添加额外功能。ES7 中提出了装饰器语法(目前是提案,需通过 Babel 编译)。
• 类装饰器:用于装饰类,修改类的行为。
• 方法装饰器:用于装饰类的方法,修改方法的执行逻辑。
• 用途:日志记录、性能监控、权限校验等。例如:用装饰器记录函数的执行时间。
60. 什么是迭代器?
迭代器(Iterator)是一种接口,为不同的数据结构提供统一的遍历机制。任何数据结构只要部署了 Iterator 接口,就可以通过 for...of 循环遍历。
• 迭代器的特性:有一个 next() 方法,每次调用返回一个对象 { value: 当前值, done: 是否遍历完成 }。
• 原生支持迭代器的数据结构:数组、字符串、Set、Map。
• 自定义迭代器:通过 Symbol.iterator 属性为对象部署迭代器接口。
61. 什么是前端微服务?
前端微服务是借鉴后端微服务的思想,将大型前端应用拆分为多个独立的、可独立开发、测试、部署的小型应用,每个小型应用称为一个“微应用”。
• 核心特点:
a. 独立部署:每个微应用可单独发布,不影响其他微应用。
b. 技术栈无关:不同微应用可使用不同的前端框架(如 Vue、React)。
c. 共享基础资源:共享公共组件、工具库、状态管理等。
d. 运行时集成:通过主应用(基座)加载微应用,实现页面跳转和通信。
• 实现方案:基于 qiankun、single-spa 等框架。