# interview
**Repository Path**: ifercarly/interview
## Basic Information
- **Project Name**: interview
- **Description**: 面试题目进阶
- **Primary Language**: Unknown
- **License**: MulanPSL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 43
- **Forks**: 9
- **Created**: 2021-09-04
- **Last Updated**: 2025-06-16
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 面试
## README
## 00. [BFC](./resource/00/README.md) ✔
## 01. [HTTP Cache](./resource/01/README.md) ✔
## 02. [new](./resource/02/README.md) ✔
## 03. [instanceof](./resource/03/README.md) ✔
## 04. [DeepClone](./resource/04/README.md) ✔
## 05. [~~发布订阅和观察者~~](./resource/05/README.md) ✔
## 06. [Vue 双向数据绑定](./resource/06/README.md) ✔
## 07. [敲回车后发生了甚么事情](./resource/07/README.md) ✔
## 08. [写个 Promise](./resource/08/README.md)
## 09. [洋葱模型](./resource/09/README.md) ✔
## 10. [Node 事件循环](./resource/10/README.md)
## 11. [数组去重](./resource/11/README.md) ✔
## 12. [React Fiber](./resource/12/README.md)
## 13. [React setState](./resource/13/README.md)
## 14. [Vue nextTick](./resource/14/README.md)
## 15. [DOM Diff](./resource/15/README.md)
## 16. [Webpack 优化](./resource/16/README.md)
## 17. [Type 和 Interface](./resource/17/README.md)
## 18. [关于 HTTPS](./resource/18/README.md) ✔
## 19. [Node Stream](./resource/19/README.md) ✔
## 20. [关于 Vue3](./resource/20/README.md)
## 21. [history 路由模式上线时后端做什么](./resource/21/README.md)
## 22. [柯里化](./resource/22/README.md) ✔〽
## 23. [Async 和 Defer](./resource/23/README.md) ✔
## 24. [Vuex 原理](./resource/24/README.md)
## 25. [设计模式](./resource/25/README.md)
## 26. [RBAC](./resource/26/README.md) ✔
## 27. [常见排序算法](./resource/27/README.md) 〽
## 28. [v-for 和 v-if 为什么不能一起用](./resource/28/README.md)
## 29. [拍平数组](./resource/29/README.md)
## 30. [Array to tree](./resource/30/README.md)
## 31. [Vue 父子生命周期](./resource/31/README.md)
## 32. [Polyfill call、apply、bind](./resource/32/README.md) ✔
## 33. [Map、Set、WeakMap、WeakSet](./resource/33/README.md)
## 34. [Class 中的箭头函数和其中的 this](./resource/34/README.md)
## 35. [Debounce / throttle](./resource/35/README.md) ✔
## 36. [HTTP2](./resource/36/README.md) ✔
## 37. [Promise.all](./resource/37/README.md)
## 38. [Why vue3 uses proxy instead](./resource/38/README.md)
## 39. [骨架屏原理](./resource/39/README.md)
## 40. [小程序支付](./resource/40/README.md)
## 41. [ES 新特性](./resource/41/README.md)
## 42. [JS Extends](./resource/42/README.md)
## 43. [RequestAnimationFrame](./resource/43/README.md)
## 44. [Redraw & reflow](./resource/44/README.md) ✔
## 45. [flex 是哪几个属性的简写](./resource/45/README.md)
## 46. [Vue Router 钩子](./resource/46/README.md)
## 47. [for/in & for/of](./resource/47/README.md) ✔
## 48. [MutationObserver](./resource/48/README.md)
## 49. [Vue.extend](./resource/49/README.md)
## 50. [代码规定](./resource/50/README.md)
## 51. [路由传参](./resource/51/README.md)
## 52. [头条项目优化](./resource/52/README.md)
## 53. [Event Loop](./resource/53/README.md) ✔
## 54. [长列表优化](./resource/54/README.md)
## 55. [Generator](./resource/55/README.md)
## 56. [Padding 实现图片的自适应](./resource/56/README.md)
## 57. [数据结构和算法](./resource/57/README.md)
## 58. [SASS 语法进阶](./resource/58/README.md)
## 59. [Vue SSR 基础](./resource/59/README.md)
## 60. [Vue SSR 案例](./resource/60/README.md)
## 61. [Mock.js](./resource/61/README.md)
## 62. [界面访问控制](./resource/62/README.md)
## 63. [BEM](./resource/63/README.md)
## 64. [原子化 CSS](./resource/64/README.md)
## 65. [React SSR](./resource/65/README.md)
## 66. [中台是啥](./resource/66/README.md)
## 67. [TypeScript](./resource/67/README.md)
```bash
Todo: Vue React 八股
flex
Node EventLoop
数据结构和算法
```
## 68. [BFF](./resource/68/README.md)
## 69. RxJS
## 70. 微前端
## 71. CI/CD
## 72. Docker
## 73. 大数问题
## 74. 位运算
## 75. Webpack 生命周期
## 76. Axios 跨域原理
## 77. 错误捕获和监控
## 78. 一次性把大量元素插入到页面
## 79. 闭包应用场景(什么时候释放)
## 80. 移动端一屏页面展示
## 81. [git merge 和 git rebease](./resource/81/README.md)
## 82. [为什么要对 URL 中的参数进行编码](./resource/82/README.md)
## 83. will-change
## 84. flutter
## 85. loader 和 plugin
## 86. 白屏
## 87. BeforeDestroy 可以操作 DOM 吗
## 88. import 和 require 的区别
## 89. Webpack Plugin 生命周期
## 90. transform 和 fixed 相互影响的问题
## 91. [qiankun](https://qiankun.umijs.org/zh/)、[G6](http://antv-2018.alipay.com/zh-cn/g6/3.x/demo/index.html)、[X6](https://x6.antv.vision/zh/docs/tutorial/about)、[Jest](https://www.jestjs.cn/)
## 92. Performance
## 93. Bundle 和 Chunk
## 94. Web Workers
## 95. WebSocket 心跳机制
## 96. 动态表单
## 97. [OpenId 和 uid](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html)
## 98. [移动端网页如何分享到微信](./resource/98/README.md)
## 99. [第三方登录](./resource/99/README.md)
## 100. [网页支付宝支付](./resource/100/README.md)
## 101. 生成 1 ~ 100
```js
;[...Array(100).keys()]
```
## 102. 转发,移动端网页如何分享到微信?
[官网](https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html)
\1. 绑定域名到微信公众号的后台。
\2. 引入微信官网提供的 JS 文件。
\3. 通过 `wx.config` 接口注入权限验证配置。
```js
wx.config({
debug: true, // 开启调试模式,调用的所有 api 的返回值会在客户端 alert 出来,若要查看传入的参数,可以在 pc 端打开,参数信息会通过 log 打出,仅在 pc 端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的 JS 接口列表
});
```
\4. 调用微信提供的相关分享接口。
```js
wx.ready(function () {
//需在用户可能点击分享按钮前就先调用
wx.updateAppMessageShareData({
title: '', // 分享标题
desc: '', // 分享描述
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号 JS 安全域名一致
imgUrl: '', // 分享图标
success: function () {
// 设置成功
},
})
})
```
## 103. 撤销
## 104. 低代码实现思路
## 105. flex 骰子
## 106. Canvas 水印
## 107. 不用循环生成序号
```js
Array.from(Array(11), (_, index) => index + 1)
[...Array(11).keys()].map((_, index) => index + 1)
```
## 108. 写一个 Pick
## 109. 前端安全
## 110. rebase
场景 1:让提交记录变得简洁。
```bash
git rebase -i 版本号 # 会合并指定版本号之后的所有 commit 记录
git rebase -i HEAD~3 # 从当前开始合并最近的三条记录
```
场景 2:合并分支。
```bash
// # 使用方式 1
git checkout dev
git rebase master
git checkout master
git merge dev
// # 使用方式 2
git checkout master
git rebase dev
```
就是历史时间线的区别,merge 保留了你所有的操作记录,而 rebase 把提交的节点变成了线性的时间线,如果分支 merge 很多的话,时间线会错综复杂,这个时候 rebase 的好处就出现了,对人肉追溯比较友好。
git rebase 发生了甚么事情?
## 111. axios 关闭请求
## 112. 组织架构数据很多
## 113. 远程组件
## 114. 权限是怎么做的
## 115. ES Modules 的静态引入
就是通过限定语法,让本来需要运行代码才能确定的依赖,可以在分析 AST 阶段就确定下来。
## 116. 两数之和
```js
/* const twoSum = function (arr, target) {
const obj = {}
for (let i = 0; i < arr.length; i++) {
if (arr[i] in obj) {
return [obj[arr[i]], i]
} else {
obj[target - arr[i]] = i
}
}
} */
const twoSum = (arr, target) => {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length; j++) {
if (arr[i] + arr[j] === target && i !== j) {
return [i, j]
}
}
}
}
const arr = [1, 2, 5, 9]
console.log(twoSum(arr, 10))
```
## 117. TS 获取对象的 key
```js
const o = {
name: 'ifer',
age: 18
}
Object.keys(o).forEach(item => {
console.log(o[item as keyof typeof o])
})
```
## 118. Promise
```js
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(233)
})
})
class Promise {
constructor(executor) {
this.status = 'pending' // Promise 的初始状态为 pending
this.value = null // Promise 的结果值
this.callbacks = [] // Promise 的回调函数数组
// executor 是一个带有 resolve 和 reject 参数的函数
// resolve 函数用于将 Promise 状态设置为 fulfilled,同时将结果值存储在 value 变量中
// reject 函数用于将 Promise 状态设置为 rejected,同时将错误原因存储在 value 变量中
try {
// 给 executor 函数传递 2 个实参,这两个实参也都是函数类型
executor(this.resolve.bind(this), this.reject.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve(value) {
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = value
this.callbacks.forEach((callback) => callback.onFulfilled(value))
}
}
reject(reason) {
if (this.status === 'pending') {
this.status = 'rejected'
this.value = reason
this.callbacks.forEach((callback) => callback.onRejected(reason))
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value
}
if (typeof onRejected !== 'function') {
onRejected = (reason) => {
throw reason
}
}
const promise = new Promise((resolve, reject) => {
if (this.status === 'fulfilled') {
setTimeout(() => {
try {
const result = onFulfilled(this.value)
this.handleResult(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (this.status === 'rejected') {
setTimeout(() => {
try {
const result = onRejected(this.value)
this.handleResult(result, resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
this.callbacks.push({
onFulfilled: (value) => {
try {
const result = onFulfilled(value)
this.handleResult(result, resolve, reject)
} catch (error) {
reject(error)
}
},
onRejected: (reason) => {
try {
const result = onRejected(reason)
this.handleResult(result, resolve, reject)
} catch (error) {
reject(error)
}
},
})
}
})
return promise
}
catch(onRejected) {
return this.then(null, onRejected)
}
handleResult(result, resolve, reject) {
if (result instanceof Promise) {
result.then(resolve, reject)
} else {
resolve(result)
}
}
static resolve(value) {
return new Promise((resolve) => resolve(value))
}
static reject(reason) {
return new Promise((_, reject) => reject(reason))
}
static all(promises) {
const results = new Array(promises.length)
let count = 0
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
Promise.resolve(promise).then((value) => {
results[index] = value
count++
if (count === promises.length) {
resolve(results)
}
}, reject)
})
})
}
}
```
## 119. 去重
```js
const arr = [
{ name: "xiaoming", age: 19 },
{ name: "xiaoming", age: 20 },
{ name: "xiaoming", age: 18 },
{ name: "xiaohong", age: 30 }
]
```
```js
const result = Object.values(arr.reduce((acc, cur) => {
if (!acc[cur.name] || acc[cur.name].age < cur.age) {
acc[cur.name] = cur;
}
return acc;
}, {}));
```
## 120. [组件二次封装](./resource/120/README.md)
优先 CSS;回归操作 DOM,自由自在。
```html
多文件上传的两层含义:一个一个选择,循环单文件,调用单文件上传的接口到后端;直接选择多文件。
切片上传。
```js
function upload(blobOrFile) {
const xhr = new XMLHttpRequest();
xhr.open('POST', '/server', true);
xhr.onload = function(e) { ... };
xhr.send(blobOrFile);
}
document.querySelector('input[type="file"]').addEventListener('change', function(e) {
let blob = this.files[0];
const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes.
const TOTAL = blob.size;
let start = 0;
// 这个 end 表示 slice 的截取结束位置
let end = BYTES_PER_CHUNK;
while(start < TOTAL) {
upload(blob.slice(start, end));
start = end;
end = start + BYTES_PER_CHUNK;
}
}, false);
```
### Blob
属性、截取方法、转换方法。
```js
const blob = new Blob(["Hello, world!"], { type: "text/plain" });
// #1 属性
console.log(blob.size); // 13 byte
console.log(blob.type);
// #2 截取方法
const partialBlob = blob.slice(0, 5);
console.log(partialBlob); // 返回一个新的 blob 对象
// #3 转换方法(这儿也可以借助 FileReader 进行转换)
// text(),该方法将 Blob 的内容读取为文本字符串,它返回一个 Promise,解析为文本数据。
partialBlob.text().then(console.log); // Hello
// arrayBuffer(),该方法将 Blob 的内容读取为 ArrayBuffer 对象,适合处理二进制数据,它返回一个 Promise,解析为 ArrayBuffer 数据。
partialBlob.arrayBuffer().then(console.log);
// stream(),该方法将 Blob 的数据作为一个 ReadableStream 返回,允许你以流的方式处理数据,适合处理大文件。
```
应用场景。
```js
// 下载
const url = URL.createObjectURL(blob); // 创建一个 Blob URL
const a = document.createElement("a");
a.href = url;
a.download = "test.txt";
a.click();
URL.revokeObjectURL(url); // 释放 URL 对象
```
```js
// 上传
// 你可以通过 FormData 对象将 Blob 作为文件上传到服务器
const formData = new FormData();
formData.append("file", blob, "example.txt");
fetch("/upload", {
method: "POST",
body: formData,
}).then((response) => {
console.log("File uploaded successfully");
});
```
### File
File => Base64
```js
// 读取 File 对象为图片
oFile.onchange = function (e) {
console.log(e.target.files[0]);
};
// 通过 FileReader 的 readAsDataURL 方法读取 File 为 base64
```
可以使用 Input File 框的方式来得到 File,我们也可以手动创建 File 对象:
```js
const file = new File(["Hello, world!"], "hello-world.txt", {
type: "text/plain",
});
```
File 是 Blob 的子类,File 对象除了具有 Blob 的所有属性和方法之外,还包含文件的元数据,如文件名和修改日期,你可以将 File 对象看作是带有文件信息的 Blob。
## 122. 文件下载
1\. `window.open()`,无法命名,当后端以 GET 的方式返回 blob 的数据可使用。
2\. 利用 a 标签的 download 属性。
```js
axios.get('http://xxx', { responseType: 'blob' }, function() {
if (window.navigator.msSaveBlob) {
} else {
// #1 创建 blobURL
const blobURL = URL.createObjectURL(后端返回的文件信息)
// #2 创建 a 标签
const a = document.createElement('a')
// #3 把 blobURL 给 a 标签的 href 属性
a.href = blobURL
// #4 给标签设置 download 属性
a.download = 'xxx.ppt'
// #5 隐藏 a 标签
a.style.display = 'none'
// #6 主动触发 a 标签的点击
a.click()
// #7 释放内存中的 blobURL
URL.revokeObjectURL(blobURL)
}
})
```
3\. [file-saver](https://www.npmjs.com/package/file-saver)
## 123. Excel / Word
| | 通用 | Vue | React |
| -------- | ---- | ---------------------------- | ----------------- |
| 解析内容 | xlsx | xlsx | xlsx |
| 预览内容 | xlsx | @vue-office/excel、docx、pdf | react-file-viewer |
Blob => ArrayBuffer => Read 方法读为 book 对象 => 提取出对应 sheet 对象 => 输出为 HTML/JS 等;创建 workbook,输出 excel。
1\. 把 DOM 结构转成 Excel 对象。
```js
import { writeFile } from 'xlsx'
htmlToSheet() {
// const tableDOM = this.$refs.tableDOM.$el.querySelector('table')
const tableDOM = this.$refs.tableDOM
const ws = utils.table_to_sheet(tableDOM)
const wb = utils.book_new()
utils.book_append_sheet(wb, ws, 'sheet1')
writeFile(wb, 'xxx.xlsx')
}
```
2\. 把 JS 对象转为 Excel 对象。
```js
dataToSheet() {
// workSheet
const ws = utils.json_to_sheet(this.tableData)
// workbook
const wb = utils.book_new()
utils.book_append_sheet(wb, ws, 'sheet1')
writeFile(wb, 'xxx.xlsx')
}
```
1\. 本地选择读取为 HTML 或 JS 对象。
```ts
uploadFile(e) {
const _file = e.target.files[0]
_file.arrayBuffer().then(r => {
// workbook
const wb = read(r)
// 取表一
const sheet1 = wb.Sheets.Sheet1
// console.log(utils.sheet_to_json(sheet1))
this.html = utils.sheet_to_html(sheet1)
// utils.sheet_to_csv(sheet1)
})
}
```
2\. 请求接口读取为 HTML 或 JS 对象。
```js
axios.get('https://xxx', { responseType: 'blob' }).then(res => {
res.data.arrayBuffer().then(res => {
// ...
})
})
```
`预览`
```html
全选 | 名字 | 年龄 | 状态 | 操作 |
{{ item.name }} | {{ item.age }} | 状态 0 状态 1 状态 2 |