盒子模型、红色的宽高度是多少
box-sizing: border-box; background: red; width: 200px; height: 200px; padding: 10px; border: 1px solid #CCC;
content-box,width就是盒子内容宽度,220px,border-box,width包括了内容和padding和border宽度,所以红色宽高应该是198px,简单题但是没反应过来说了222px
水平垂直居中的方法
一道算法题,三数之和等于目标值
const findSumTarget = (list, target) => {
const n = list.length;
for (let i = 0; i < n; i++) {
const num = list[i];
let left = i + 1;
let right = n - 1;
while (left < right) {
const sum = num + list[left] + list[right];
if (sum === target) {
return [num, list[left], list[right]];
} else if (sum < target) {
left++;
} else {
right--;
}
}
}
};
const list = [1, 2, 3, 4, 5, 9, 12];
console.log(findSumTarget(list, 8));
const findSumTarget = (list, target) => {
const n = list.length;
for (let i = 0; i < n; i++) {
const num = list[i];
let left = i + 1;
let right = n - 1;
while (left < right) {
const sum = num + list[left] + list[right];
if (sum === target) {
return [num, list[left], list[right]];
} else if (sum < target) {
left++;
} else {
right--;
}
}
}
};
const list = [1, 2, 3, 4, 5, 9, 12];
console.log(findSumTarget(list, 8));
异步问题,不固定长度的异步队列,怎么按顺序执行,怎么同步执行
按顺序执行:async配合await,使用for of去遍历,不能用forEach,因为forEach是同步,也不能用普通的for和while因为不知道长度
async function executeWithChaining(tasks) {
let result;
for (const task of tasks) {
result = await task(result); // 将前一个任务的结果传递给下一个任务
}
}
async function executeWithChaining(tasks) {
let result;
for (const task of tasks) {
result = await task(result); // 将前一个任务的结果传递给下一个任务
}
}
同步执行:Promise.all
Promise的API知道哪些,他们具体的使用场景是哪些
Promise.all:接受一个可迭代对象(通常是一个数组项为 promise 的数组),并返回一个新的 promise。同时请求多个请求
Promise.race:等待第一个 settle 的 promise,并将其 result/error 作为结果返回。超时报错可以用它
Promise.allSettled:等待所有的 promise 都被 settle,无论结果如何。例如,我们想要获取(fetch)多个用户的信息。即使其中一个请求失败,我们仍然对其他的感兴趣。
Promise.any:(ES2021 新增方法)—— 等待第一个 fulfilled 的 promise,并将其结果作为结果返回。如果所有 promise 都 rejected,Promise.any 则会抛出 AggregateError 错误类型的 error 实例。
Promise.resolve(value) —— 使用给定 value 创建一个 resolved 的 promise。
Promise.reject(error) —— 使用给定 error 创建一个 rejected 的 promise。
tree-shaking的原理
Tree-Shaking 的工作流程 以 Webpack 为例:
解析入口文件:从入口开始构建依赖图。 静态分析:检查每个模块的 import/export,标记未使用的导出。 标记死代码:在抽象语法树(AST)层面移除未使用的代码。 压缩与输出:通过 Terser 等工具进一步压缩代码。
cdn的原理
http缓存
强缓存
Cache-Control:当值设为max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。 Expires:过期时间,如果设置了时间,则浏览器会在设置的时间内直接读取缓存,不再请求
协商缓存
Etag/If-None-Match
Etag:
Etag是属于HTTP 1.1属性,它是由服务器(Apache或者其他工具)生成返回给前端,用来帮助服务器控制Web端的缓存验证。 Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
If-None-Match:
当资源过期时,浏览器发现响应头里有Etag,则再次像服务器请求时带上请求头if-none-match(值是Etag的值)。服务器收到请求进行比对,决定返回200或304
Last-Modifed/If-Modified-Since
Last-Modified:
服务器向浏览器发送最后的修改时间
If-Modified-Since:
当资源过期时(浏览器判断Cache-Control标识的max-age过期),发现响应头具有Last-Modified声明,则再次向服务器请求时带上头if-modified-since,表示请求时间。服务器收到请求后发现有if-modified-since则与被请求资源的最后修改时间进行对比(Last-Modified),若最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;若最后修改时间较旧(小),说明资源无新修改,响应HTTP 304 走缓存。
Last-Modifed/If-Modified-Since的时间精度是秒,而Etag可以更精确。 Etag优先级是高于Last-Modifed的,所以服务器会优先验证Etag Last-Modifed/If-Modified-Since是http1.0的头字段
做过哪些首屏优化
字体压缩、gzip压缩、路由懒加载、组件懒加载、组件按需引入、echarts按需引入
Vue2和Vue3比缺陷是什么
Proxy和Object.defineProprietary的区别
Vue2和Vue3的实现API相比,他的具体getter收集的步骤什么的不同,导致他性能不同
性能差异的关键原因
Vue2 的性能瓶颈
- 初始化开销大:
对于大型对象或嵌套结构,需递归遍历所有属性并定义 getter/setter,时间复杂度为 O(n)。
- 冗余依赖收集: 每个属性独立维护依赖列表,若多个属性被同一副作用依赖,会导致重复收集。
- 数组操作低效: 数组的变异方法(如 push/pop)需要额外劫持,且无法检测非整数索引的属性变化。
Vue3 的优化
- 惰性初始化: 通过 Proxy 代理对象,无需在初始化时遍历所有属性,仅在属性被首次访问时触发 getter。
- 依赖去重: 按副作用分组依赖,避免同一副作用多次收集相同依赖。
- 高效数组操作: Proxy 可以直接拦截数组的变异操作,无需特殊处理。
- 静态提升与缓存: 编译阶段标记静态节点,减少运行时依赖收集次数。
Vue2和Vue3的diff算法差异原理
最长递增子序列