前端基础知识
一、Ajax Fetch Axios 三者区别
1. 三者都用于网络请求,但是不同维度
- Ajax ( Asynchronous Javascript and XML ) ,一种技术统称
- Fetch ,一个具体的 API
- Axios ,是一个第三方库
2. 用 XMLHttpRequest 实现 Ajax
js
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://www.baidu.com', false)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
xhr.send(null)3. Fetch
- 浏览器原生 API ,用于网络请求
- 和 XMLHttpRequest 一个级别
- Fetch 语法更简洁、易用,支持 Promise
4. Axios
- 最常用的网络请求 lib (随 Vue 火爆起来)
- 内部可用 XMLHttpRequest 和 Fetch 实现
5. 答案
- Ajax - 一种技术统称
- Fetch - 一个原生 API
- Axios - 一个第三方库
6. 划重点
- lib 和 API 区别
- 实际项目中,使用现成的 lib ,尽量不要自己造轮子
- 但读源码,造轮子是很好的个人学习方式
二、节流和防抖
1. 题目
- 防抖和节流有什么区别
- 分别应用到什么场景
2. 防抖
- 防抖,防止抖动 “ 你先抖动着,什么时候停 ” 再执行下一步
- 例如:一个搜索输入框,等输入停止之后,再触发搜索
3. 防抖 - 代码
js
const input = document.getElementById('input')
input.addEventListener('keyup', debounce(function () {
console.log('提交', this.value)
}, 300))
function debounce(fun, delay = 200) {
let timer = null
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fun.apply(this, arguments) // 透传 this 和 参数
timer = null
}, delay)
}
}4. 防抖 - 示意图

5. 节流
- 节流,节省交互沟通。流,不一定至流量
- “ 别急,一个一个来,按时间节奏来,插队者无效 ”
- 例如,drag 和 scroll 期间触发某个回调,要设置一个时间间隔
6. 节流 - 代码
js
const div = document.getElementById('div')
input.addEventListener('drag', debounce(function (e) {
console.log('拖动', e.offsetX, e.offsetY)
}, 100))
function debounce(fun, delay = 200) {
let timer = null
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fun.apply(this, arguments) // 透传 this 和 参数
timer = null
}, delay)
}
}7. 节流 - 示意图

8. 答案
- 节流:限制执行频率,有节奏的执行
- 防抖:限制执行次数,多次密集的触发只执行一次
- 节流关注 “过程” ,防抖关注 “结果”
三、px % em rem vw vh 的区别
1. px 和 %
- px 基本单位,绝对单位(其他的都是相对单位)
- % 相对父元素的宽度比例
2. em 和 rem
- em 是根据当前元素的 font-size
- rem 是根据根节点的 font-size
3. vw 和 vh
- vw 是屏幕宽度的 1 %
- vh 是屏幕高度的 1 %
- vmin 两者间的最小值,vmax 两者间的最大值
四、箭头函数
1. 题目
- 箭头函数有什么缺点
- 什么时候不能使用箭头函数
2. 箭头函数缺点
- 没有 arguments
- 无法通过 apply call bind 改变 this
- 某些箭头函数的代码难以阅读
3. 不适用场景
对象方法
jsconst obj = { name: 'lzz', getName: () => { return this.name } }原型方法
jsconst obj = { name: 'lzz' } obj.__proto__.getName = () => { return this.name }构造函数
jsconst Foo = (name, age) => { this.name = name this.age = age } const foo = new Foo('lzz', 24) // Foo is not a constructor动态上下文中的回调函数
jsconst btn = document.getElementById('btn') btn.addEventListener('click', () => { // console.log(this === window) // true this.innerText = 'clicked' })Vue 的生命周期和 method
js{ data() { return {name: 'lzz'} }, method: { getName: () => { // 报错 Cannot read properties of undefined (reading 'name') return this.name } // getName() { // return this.name // 正常 // } }, mounted:() => { // 报错 Cannot read properties of undefined (reading 'name') console.log(this.name) } // mounted() { // console.log(this.name) // 正常 // } }- Vue 组件本质上是一个 JS 对象
- React 组件(非 Hooks)它本质上是一个 ES6 class(可以使用箭头函数)
4. 划重点
- 要熟练使用箭头函数,也要对函数 this arguments 敏感
- 传统 Vue 组件是 JS 对象,传统 React 组件是 class ,两者不同
五、请描述 TCP 三次握手四次挥手
1. 建立 TCP 连接
- 先建立连接(确保双方都有收发消息的能力)
- 再传输内容(如发送一个 get 请求)
- 网络连接是 TCP 协议,传输内容是 HTTP 协议
2. 三次握手 - 建立连接
- Client 发包,Server 接收。Server:有 Client 找我
- Server 发包,Client 接收。Client:Server 已经接收到消息了
- Client 发包,Server 接收。Server:Client 要准备发送了
3. 四次挥手 - 断开连接
- Client 发包,Server 接收。Server:Client 已请求结束
- Server 发包,Client 接收。Client:Server 已经收到,我等待它关闭
- Server 发包,Client 接收。Client:Server 此时已经可以关闭了
- Client 发包,Server 接收。Server:可以关闭了(然后关闭连接)
4. 图解


5. 划重点
- 握手是连接,挥手是告别
六、for ... in 和 for ... of 的区别
1. key 和 value
- for ... in 遍历得到 key
- for ... of 遍历得到 value
2. 适用于不同数据类型
遍历对象:for ... in 可以,for ... of 不可以
遍历 Map Set :for ... of 可以,for ... in 不可以
遍历 generator:for ... of 可以,for ... in 不可以
js// 遍历 generator function* foo() { yield 10 yield 20 yield 30 } for (const y of foo()) { console.log(y) // 10 20 30 } // 拓展:generator 常用场景 // 为不具备 Iterator 接口的对象提供遍历方法 function* objectEntries(obj) { for (const propKey of Object.keys(obj)) { yield [propKey, obj[propKey]]; } } const jane = { first: 'Jane', last: 'Doe' }; for (const [key,value] of objectEntries(jane)) { console.log(`${key}: ${value}`); // first: Jane last: Doe }
3. 可枚举 vs 可迭代
for ... in 用于 可枚举 数据,如对象、数组、字符串
for ... of 用于 可迭代 数据,如数组、字符串、Map、Set

4. 答案
- for ... in 用于 可枚举 数据,如对象、数组、字符串,得到 key
- for ... of 用于 可迭代 数据,如数组、字符串、Map、Set,得到 value
七、(连环问) for await ... of 有什么用
1. 答案
for await ... of 用于遍历多个 Promise
jsfunction createPromise(val) { return new Promise(resolve => { setTimeout(() => { resolve(val) }, 3000) }) } (async function () { const p1 = createPromise(100) const p2 = createPromise(100) const p3 = createPromise(100) // const res1 = await p1 // const res2 = await p2 // const res3 = await p3 const list = [p1, p2, p3] Promise.all(list).then(res => console.log(res)) for await (let res of list) { console.log(res) } // 顺序调用 const res1 = await createPromise(100) console.log(res1) const res2 = await createPromise(200) console.log(res2) const res3 = await createPromise(300) console.log(res3) const arr = [100, 200, 300] for (let num of arr) { const res = await createPromise(num) console.log(res) } })()
八、offsetHeight scrollHeight clientHeight 区别
1. 计算规则
- offsetHeight / offsetWidth:border + padding + content
- clientHeight / clientWidth:padding + content
- scrollHeight / sceollWidth:padding + 实际内容尺寸(包括里面内容)
九、HTMLCollection 和 NodeList 区别
1. Node 和 Element
- DOM 是一棵树,所有节点都是 Node
- Node 是 Element 的基类
- Element 是其他 HTML 元素的基类,如 HTMLDivElement

2. HTMLCollection 和 NodeList
- HTMLCollection 是 Element 的集合
- NodeList 是 Node 集合
3. 划重点
- 获取 Node 和 Element 的返回结果可能不一样
- 如 elem.childNodes 和 elem.children 不一样
- 前者会包含 Text 和 Comment 节点,后者不会
4. 扩展:类数组 -> 数组
js
// HTMLCollection 和 NodeList 都不是数组, 而是 "类数组"
const arr1 = Array.from(list)
const arr2 = Array.prototype.slice.call(list)
const arr3 = [...list]十、Vue computed 和 watch 区别
1. 两者用途不同
- computed 用于计算产生新的数据
- watch 用于监听现有数据
2. computed 有缓存
- computed 有缓存
- method 没有缓存
十一、Vue 组件通讯有几种方式
1. Vue 组件通讯有几种方式
props 和 $emit
自定义事件(Vue3 中要单独引 event-emitter 库)
$attr
$parent
$refs
provide / inject
js// 静态 provide: { info: 'aaa' } // 响应式 provide() { return { info: computed(() => this.name) } } // 接收 inject: ['info']Vuex
2. 不同场景
- 父子组件
- 上下级组件(跨多级)通讯
- 全局组件
十二、Vuex mutation action 区别
1. 区别
- mutation:原子操作;必须同步代码
- action:可包含多个 mutation ;可包含异步代码
十三、JS 严格模式有什么特点
1. 开启严格模式
js
'use strict' // 全局开启
function fn() {
'use strict' // 某函数开启
}2. 特点
全局变量必须先声明
禁止使用 with
jsconst obj = { x: 100, y: 200 } with (obj) = { console.log(x, y) // obj.x obj.y }创建 eval 作用域
js'use strict' var x = 10 eval(`var x = 20; console.log('in eval', x);`) // 20 很不推荐使用 eval console.log('out eval', x); // 10禁止 this 指向 window
js'use strict' function fn() { console.log('this', this) //undefined } fn()函数参数不能重名
十四、HTTP 跨域为何要发送 options 请求
1. 跨域请求
- 浏览器同源策略
- 同源策略一般限制 Ajax 网络请求,不能跨域请求 server
- 不会限制
<link> <img> <script> <iframe>加载第三方资源
2. JSONP

3. CORS

4. 答案
- options 请求,是跨域请求前的预检查
- 浏览器自行发起的,无需我们干预
- 不影响实际功能
十五、Restful API 常用 method
GET查询POST新增PATCH更新- 跟
PATCH很像的还有PUT方法,两者有差别PUT更新全部内容,即替换PATCH更新部分内容 —— 更加常用
- 跟
DELETE删除