面试记录
2022.08.19量投科技
2022.08.22鲁班软件
1. TS泛型的理解
- 在定义函数、接口或者类的时候,不预先指定具体的类型,而是在使用的时候再指定类型的一种特性。
- 提高代码可重用性,使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。
function f<T>(arg: T): T {
return arg;
}
2. html性能优化
- HTML 优化 减少 iframes 的使用,
- 父 html 需要等待所有 iframe 加载完成
- 压缩空白符
- 避免节点深层次的嵌套
- 避免 table 布局
- 删除注释
- css&javascript 尽量外链
- 删除元素默认属性
3. css性能优化
- 内联首屏关键css
- 异步加载非首屏css
- css文件压缩
- css层级嵌套最好不要超过3层
- 删除无用css代码
- 慎用*通配符
- 小图片用雪碧图,字体图标或者转成base64
- 避免使用@import
- 优化回流和重绘
4. ES6中的数组方法
- forEach
- map
- filter
- find
- every
- some
- reduce
5. ajax, axios, fetch区别
ajax
- 局部刷新页面,无需重载整个页面。
简单来说,Ajax 是一种思想,XMLHttpRequest 只是实现 Ajax 的一种方式
fetch
- 使用 promise,不使用回调函数。
- 采用模块化设计,比如 rep、res 等对象分散开来,比较友好。
- 通过数据流对象处理数据,可以提高网站性能。
axios
Axios 是一个基于 promise 封装的网络请求库,它是基于 XHR 进行二次封装
- 从浏览器中创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 XSRF
6. for,forEach和map的区别
- 在固定长度或者长度不需要计算的时候for循环效率高于foreach和map,for循环中可以通过break终止。
- 在不确定长度或者计算长度有损性能的时候用foreach和map比较方便
相同点:
都是循环遍历数组中的每一项
forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是item(当前每一项),index(索引值),arr(原数组)
匿名函数中的this都是指向window
只能遍历数组
都不会改变原数组
不同点:
- map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值
- forEach方法不会返回新数组
性能:
- for > forEach > map
- for 循环当然是最简单的,因为它没有任何额外的函数调用栈和上下文
- forEach 其次,因为它其实比我们想象得要复杂一些。它不是普通的 for 循环的语法糖,还有诸多参数和上下文需要在执行的时候考虑进来,这里可能拖慢性能;
- map 最慢,因为它的返回值是一个等长的全新的数组,数组创建和赋值产生的性能开销很大。
7. 性能优化方案
- 减少HTTP请求
- 使用服务端渲染
- 静态资源使用CDN
- CSS文件放在头部,JS文件放在底部
- 善用缓存,不重复加载相同的资源
- 压缩文件
- 图片延迟加载
- 使用事件委托
- 使用Web Workers
2022.08.23 聚水潭
2022.08.29 拼多多
1. 实现Promise重试
function runWithRetry(fn, retryTimes) {
return fn().then(res => {
return res;
}).catch(err => {
if (retryTimes === 0) {
return Promise.reject(err)
}
return runWithRetry(fn, retryTimes - 1)
})
}
function asyncApp() {
return new Promise((resolve, reject) => {
if (Math.random() > 0.7) {
resolve('success');
console.log('success');
} else {
reject('failed')
console.log('failed');
}
})
}
runWithRetry(asyncApp, 3)
2. Promise的输出
function asyncApp() {
return new Promise((resolve, reject) => {
reject('failed')
resolve('success');
})
}
asyncApp().then(res => {
console.log('then1', res);
}).then(res => {
console.log(('then2', res));
}).catch(err => {
console.log('catch1', err);
}).then(res => {
console.log('then3', res);
})
// 输出
catch1 failed
then3 underfined
3. 倒计时组件
function CountDown({ process }) {
const [count, setCount] = useState(process);
useEffect(() => {
setCount(process);
}, [process]);
useEffect(() => {
let id = null;
if (count > 0) {
id = setTimeout(() => {
setCount(count - 1);
}, 1000);
}
return () => {
clearTimeout(id);
};
}, [count]);
return <div>{count}</div>;
}
4. defer和async的区别
- defer, 当浏览器遇到带有 defer 属性的 script 时,获取该脚本的网络请求也是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器不会暂停解析并执行 JS 代码,而是等待 HTML 解析完毕再执行 JS 代码
- async, 当浏览器遇到带有 async 属性的 script 时,请求该脚本的网络请求是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器会暂停解析,先让 JS 引擎执行代码,执行完毕后再进行解析
5. flex
- flex-grow: 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
- flex-shrink: 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
- flex-basis: 定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小
- flex-wrap: 定义,如果一条轴线排不下,如何换行
6. CSS选择器
// 同时有a, b两个class .a.b { color: red }
// a元素内的所有b子元素 .a .b { color: red }
// 父级是a元素的b元素 .a > .b { color: red }
// 紧跟在a元素后的第一个b元素 .a + .b { color: red }
7. 用过哪些抓包工具
2023.08.09 收钱吧
1. 如何画一个梯形和三角形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.wrap1 {
width: 200px;
border-bottom: 200px solid red;
border-top: 200px solid transparent;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
}
.wrap2 {
width: 0px;
border-bottom: 200px solid red;
border-top: 200px solid transparent;
border-left: 200px solid transparent;
border-right: 200px solid transparent;
}
</style>
</head>
<body>
<!-- 梯形 -->
<div class="wrap1"></div>
<!-- 三角形 -->
<div class="wrap2"></div>
</body>
</html>
2. position 有哪些属性
- static 默认值 没有定位,元素出现在正常的流中
- absolute 绝对定位,相对于static定位外的第一个父元素进行定位
- relative 相对定位,相对于其正常位置进行定位
- fixed 固定定位,相对于浏览器窗口进行定位
- sticky 粘性定位,基于用户滚动的位置
- inherit 继承父元素
- initial 设置该属性为默认值
3. hooks和普通函数的区别
- hooks只能在React函数组件中调用
4. 遍历数组的方法
- for循环
- for of
- forEach
- map
- filter
- reduce
- every
- some
- find
5. 如何实现message弹窗
6. 箭头函数和普通函数的区别
- 箭头函数的this是定义时决定的,普通函数是看调用方法。
- 箭头函数不能成为构造函数
- 箭头函数不能使用call、apply、bind来修改this指向
- 箭头函数不绑定arguments ,…剩余参数
- 箭头函数不具有prototype原型对象,不具有super,不有new
2023.08.11 收钱吧二面
1. PC端开发和移动端开发的区别
2023.10.09 比心
1. 函数式编程的理解
2. 项目中如何封装组件
2023.10.16 爱回收
1. 前端高并发处理
2023.10.18 擎创科技
1. 封装InputNumber组件,支持受控和非受控模式
2. 实现getPath函数
2023.10.18 爱回收二三面
1. Grid布局
Grid布局即网格布局,将一个页面划分为几个主要区域,以及定义这些区域的大小,位置,层次等关系。
flex布局是一维布局,Grid布局是二维布局
2. git的工作流
3. react context的理解
4. react fiber的理解
5. 浏览器渲染原理
2023.10.26 爱回收加面
1. 图片资源加载失败监控
window.addEventListener('error', function (event) {
if (event.target.tagName === 'IMG') {
// 目标元素是图片
console.log('图片加载失败:', event.target.src);
// 你可以在这里执行其他处理逻辑,比如替换为默认图片等
}
}, true);
2. git rebase和git merge区别
git rebase
和 git merge
是 Git 中两种不同的分支合并策略,它们有一些关键区别:
- 历史记录的整洁性:
- **
git merge
**:合并分支后,会保留分支的完整历史记录。这意味着分支合并后,你可以清晰地看到哪个分支的提交,因为每个分支的提交历史都被保留。 - **
git rebase
**:它会将当前分支的提交依次放在目标分支的最新提交之后,使得提交历史变得线性和整洁。这会让你的提交历史更容易理解,但也可能丧失分支的完整性。
- **
- 冲突解决:
- **
git merge
**:在合并分支时,如果存在冲突,Git 会创建一个新的合并提交来解决冲突。你需要手动解决冲突,然后提交合并的结果。 - **
git rebase
**:在 rebase 过程中,如果存在冲突,Git 会暂停 rebase 过程,允许你解决冲突。你需要解决冲突,然后继续 rebase,直到完成。这可以产生一个更整洁的历史,但也需要更多的手动干预。
- **
- 分支分叉点:
- **
git merge
**:在提交历史中会保留分支的分叉点,这些分叉点显示了分支之间的合并关系。 - **
git rebase
**:它会将当前分支的提交“移动”到目标分支之后,所以看不到分叉点。这可以使提交历史更线性,但也可能使分支合并关系不太明显。
- **
- 推荐使用情况:
- **
git merge
**:适用于公共分支合并,如合并 feature 分支到主分支。保留分支完整性,清晰地记录合并点,以及允许多人协作的情况。 - **
git rebase
**:适用于在本地工作分支上同步和整理提交历史。如果你想要一个整洁的提交历史,可以在提交代码之前使用rebase
来将你的分支与目标分支同步。
- **
综上所述,git merge
和 git rebase
有各自的优点和适用场景,你可以根据具体的需求和项目情况选择合适的合并策略。
3. 金额千分位实现
function addThousandsSeparator(number) {
// 判断输入是否是数字
if (typeof number !== 'number') {
return '请输入一个有效的数字';
}
// 使用正则表达式将数字格式化为千分位
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// 示例用法:
const number = 1234567.89;
const formattedNumber = addThousandsSeparator(number);
console.log(formattedNumber); // 输出 "1,234,567.89"
4. 微前端通信
2023.11.16 友塔游戏
1. http和https的区别
2. 大数据量列表处理
3. n*n矩阵遍历
2023.11.21 友塔游戏二面
1. 输入框组件封装
2. 子序列和算法
2023.12.11 字节跳动
1. DNS
2. 服务端渲染原理
3. LCP的评判标准
4. Flex布局
5. 天降弹幕
6. 翻转二叉树
7. timeout函数封装
面试记录
http://yellowcan.top/2022/08/19/mian-shi-ji-lu/