# 字节医疗(2021/07)
# 一面
- webpcak优化
- cookie跨域
- app环境切换
- webpack各个插件原理
- 图片压缩 原理 (opens new window)
- 多线程打包
- ParallelUglifyPlugin(无人维护)
- happyPack happyPack原理 (opens new window)
- speed-measure-webpack-plugin 测各个打包阶段的时间
- thread-loader
- terser-webpack-plugin (webpack4)
- cdn原理
- 手写题
- sentry原理 错误收集 sentry (opens new window)
- tracker原理 原理 (opens new window)
- tree shaking原理
- uglifyjs 原理 压缩了什么 (opens new window)
- webpack vue-cli https的配置
# 二面
webpack优化
cdn
ssr
- cdn
- 优缺点 该怎么解决
- 区分serve和client环境
首屏优化
手写题 arrToTree
cookie跨域
跨域问题
common.js 和 es模块化区别
- 在代码中的体现
- tree shaking
- 哪些代码不容易被tree shaking
动画的实现 和原理 (回到顶部)
const scrollToTop = () => { const beginTime = Date.now() const beginValue = el.value.scrollTop const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16)) const frameFunc = () => { const progress = (Date.now() - beginTime) / 500 if (progress < 1) { el.value.scrollTop = beginValue * (1 - easeInOutCubic(progress)) rAF(frameFunc) } else { el.value.scrollTop = 0 } } rAF(frameFunc) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15环境注入的原理
# 字节广告平台
# 一面
# 一面
vue2和vue3的区别 (opens new window)
- 底层原理
cookie
- 常用属性
- 跨域
-
- 什么是BFC
- BFC有什么特点
手写题
- promise.all的实现
- 括号匹配
const str1 = '(){]' const str2 = '([]){}' const map = { '(': -1, ')': 1, '[': -2, ']': 2, '{': -3, '}': 3 } function check(str) { if(!str) { return false } if(str.length % 2) { return false } let arr = str.split('') let stack = [] for(item of arr) { if(map[item] < 0) { stack.push(item) }else { const pop = stack.pop() if(map[pop] + map[item] !== 0) { return false } } } if(stack.length) { return false } return true }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 二面
classname的用处 (opens new window) classname的实现 (opens new window)
# 字节(2021/06)
ssr
技术难点
变量提升
alert(a); a(); let a = 3; function a (){ alert(10) } alert(a); a = 6; a() // a已经定义了 // 函数提升一直存在,所以会报错a已经定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15alert(a); a(); var a = 3; function a (){ alert(10) } alert(a); a = 6; a() // 结果: // function a() {} // 10 // 3 // 报错: a不是一个函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18promise.all 实现
// const [re1, res2] = Promise.all(['', '', '']) Promise.prototype.all = function (promises) { return new Promise((resolve, reject) => { let result = [] let count = 0 let l = promises.length const resolveResult = function(data, index) { count++ result[index] = data if(count === l) { resolve(result) } } for(let i=0; i<l; i++) { if(typeof promises[i].then === 'function') { promises[i].then(res => { resolveResult(res, i) }, e => { reject(e) }) }else { resolveResult(promises[i], i) } } }) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30flex布局
- 父元素600px,子元素分别是200px并且设置了flex: 1,是什么样的展示
- 子元素的的属性,
- flex:1 是什么的缩写
- 垂直水平居中
多个异步同时拿到数据的解决方案 多种(哨兵) (opens new window); asyc/await 替代 (opens new window)
let
ts
spa页面的实现 vue-router的原理 (opens new window)
# 美团(酒店)
正则 字符串最长的数字,金额千分位
mpvue原理
typescript
- type interface区别
- 项目中用到的typscript语法有哪些
vue hooks function-api
react hooks
function Test() { const [name, setName] = useState('moyuderen') const inputEl = useRef(null) useEffect(() => { this.timer = setTimeout(() => { document.title = 'useEffect' }, 300) return () => { // 清除的内容在返回的函数内执行 clearTimeout(this.timer) } }, [name]) useEffect(() => { console.log('触发useEffect') }) const handleClick = () => { setName('zeo') inputEl.current.focus() } return( <> <p>name</p> <input ref={inputEl} type="text"/> <button onClick={handleClick}></button> </> ) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
311px rem vw/vh
缓存
nginx的配置
server { listen 80; server_name _; index index.html index.htm; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript application/xml application/json application/octet-stream image/x-icon image/png image/gif; gzip_vary on; location ~ /partners_app/brokerage-agency.html { rewrite /partners_app/brokerage-agency.html(.*) /partners_app/$1 permanent; } location / { alias /med/dist/; location ~* .*(html|json)$ { expires -1s; add_header 'Cache-Control' 'no-store'; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; } location ~* .*(js|css|png|jpeg|jpg|gif)$ { expires max; } proxy_pass http://www.baidu.com } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35vue-router的原理
vue history 后端需要配合处理什么 nginx
# nginx 去匹配url 没有就匹配到啊index.html location / { try_files $uri $uri/ /index.html; }
1
2
3
4原生Node
const http = require('http') const fs = require('fs') const httpPort = 80 http.createServer((req, res) => { // 划重点 fs.readFile('index.htm', 'utf-8', (err, content) => { if (err) { console.log('We cannot open "index.htm" file.') } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }) res.end(content) }) }).listen(httpPort, () => { console.log('Server listening on: http://localhost:%s', httpPort) })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20fetch axios 跨域 携带cookie怎么处理 有什么区别
- fetch axios都支持promise
- fetch 原生api axios是对ajax和http的封装(web/node)
- 跨域
- fetch credentials: 'include'允许所有; same-origin, omit
- fetch mode: no-cors, cors, *same-origin
- axios withCredentials: true/false
- 是否能取消 xhr.abort fetch没有
- 拦截器
新旧项目 lint冲突
- .ignore
# 快手
自我介绍
项目上的亮点难点
sentry sentry实现的原理
typescript
- typescript的优势
- interface he type的区别
- 相同点 1. 都可以描述一个对象或者函数 2. 都可以拓展和继承 - interface extends - type & 互相继承
- 不同点 1. type可以描述基本类型 2. interface能够声明合并
css
- 实现一个三角形
- 实现一个等边三角形
笔试题
// 1 var a = { x: 1 }; var b = a; a.x = a = { n: 1 }; console.log(a); console.log(b); // 2 Function.prototype.a = () => alert(1); Object.prototype.b = () => alert(2); function A() {} const a = new A(); a.a(); // 报错 a.b(); console.log(a instanceof Function) // false console.log(a instanceof Object) console.log(A instanceof Function) console.log(A instanceof Object) console.log(a instanceof A) // 3 console.log(a); var a = 0; console.log(b); let b = 0; console.log(c); function c() {} console.log(d); class d {} // 4 var x = 10; function a(y) { var x = 20; return b(y); } function b(y) { return x + y } a(20); // 30 // 5 console.log(1); setTimeout(() => { console.log(2) }); process.nextTick(() => { console.log(3); }); setImmediate(() => { console.log(4) }); new Promise(resolve => { console.log(5); resolve(); console.log(6); }).then(() => { console.log(7) }); Promise.resolve().then(() => { console.log(8); process.nextTick(() => { console.log(9) }); }) // 1, 5, 6, 3, 7, 8, 9, 2, 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74请实现一个cacheRequest方法,保证当使用ajax(请求相同资源时,此题中相同资源的判断是以url为判断依据),真实网络层中,实际只发出一次请求(假设已存在request方法用于封装ajax请求,调用格式为:
request(url, successCallback, failCallback)
)比如调用方代码(并行请求)如下// a.js cacheRequest('/user', data => { console.log('我是从A中请求的user,数据为' + data); }) // b.js cacheRequest('/user', data => { console.log('我是从B中请求的user,数据为' + data); })
1
2
3
4
5
6
7
8
9let cache = new Map() function cacheRequest(url, callback, fail) { if(cache.has(url)) { callback(cache.get(url)) }else { request(url, function(data) { cache.set(url, data) callback(data) }, fail) } }
1
2
3
4
5
6
7
8
9
10
11
# 滴滴(乘客前端)
# 高德
- 变量提升
- this
- vue原理
- vue 异步更新队列
- react 原理
- es6
- class
- 箭头函数
- let
- 缓存
强缓存
- 命中: 返回
200
, from: memory cahce/ disk cahce - 没有命中:返回 200 资源来自网络
expires
cache-control: max-age, no-store, no-cache
(每次都要去确定)
- 命中: 返回
协商缓存
last-modified / if-modified-since
etag / if-none-match
- webpack配置和优化
# 跟谁学
- css三角形
- 梯形
- 金额千分位处理:
- 12345678 => 12,345,678
- 正则
- promise原理
- promise.all 原理
- 实现一个Object.create()
- 深拷贝
# 美餐
- 重构
- 单元测试
- 开发流程
- 代码可读性 可维护性
- 如何保证代码质量
# 58 二手车业务
深拷贝
继承
原型链
webpack的优化 第三方包的处理
vue2 vue3响应式原理
native sdk原理; 封装 id
css 三角形,三列布局,
输入地址到渲染发生了什么
浏览器的缓存机制
事件循环机制 与Node的区别
是否有Node的开发经验
ts的语法 装饰器
interface City { } type Status = 1 | 2 | 3 declare module '*vue' { import Vue from 'vue' return Vue } declare const Env: string enum Status { Start: 1 Prograsss: 2 End: 3 } class Parent { }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22移动端的适配 rem
# moka
项目中遇到的坑
实现一个JSON.stringify
// 换行,逗号,缩进(记录深度),括号
var data = {
a: 1,
b: [
1,
2,
{
m: 1,
}
],
}
stringify(data)
JSON.stringify(data, null, 2)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 奇安信
- vue3的优势
- react hooks
- vue2 vue3的原理,依赖收集的时机 (opens new window)
- typescript的优势 代码质量?
- 错误上报和收集,try{} catch{}能收集异步错误嘛? unhandleReject能收集到setTimeout的错误嘛
- react setData是异步的还是同步的
# 开课吧
# 一面
function debounce(fn, wait) {
let timer = null
return function(args) {
if(timer) {
clearTimeout(timer)
return
}
timer = setTimeout(() => {
fn.call(this, ...args)
}, wait);
}
}
var arr = [1, 2, [3, [4, 5]]]
// 1. es10 flat方法
// 2.
function flat1(arr) {
let ret = []
function run(arr) {
arr.forEach(item => {
if(Array.isArray(item)) {
run(item)
}else {
ret.push(item)
}
});
}
run(arr)
return ret
}
// 3. stack
function flat2(arr) {
let stack = [...arr]
let ret = []
if (stack.length) {
const last = stack.pop()
if(Array.isArray(last)) {
stack.concat(last)
}else {
ret.push(item)
}
}
return ret.reverse()
}
function foo(a) {
console.log(this, a)
}
var obj = {
m: 222
}
foo.call(obj, 1)
Function.prototype.call = function (ctx = window, ...args) {
ctx.fn = this
const result = ctx.fn(...args)
delete ctx.fn
return result
}
function isObject(val) {
return typeof val === 'object' && val !== null
}
const obj1 = {
a: 1,
b: {
m: 1,
n: [
1,
2,
{
q: 'q'
},
]
},
p: obj1.b,
date: new Date('2022-02-11')
}
console.log(deepClone(obj1))
function deepClone(target, map = new Map()) {
if(!isObject(target)) {
return target
}
const Constructor = target.constructor
if (target instanceof Constructor) {
return new Constructor(target)
}
if(map.has(target)) {
return map.get(target)
}
let result = Array.isArray(target) ? [] : {}
map.set(target, result)
Reflect.ownKeys(target).forEach(key => {
result[key] = deepClone(target[key], map)
});
}
// p1 instanceof Parent
// P1.__proto__ === Parent.prototype
function sleep(timeout) {
return new Promise((resolve, reject) => {
const id = setTimeout(() => {
clearTimeout(id)
resolve()
}, timeout);
})
}
function fetchData(url) {
return new Promise()
}
// 实现一个本地存储,超过1d后,重新请求接口更新数据
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# umu
axios cancel 原理,保证正确的执行顺序
const CancelToken = axios.CancelToken const source = CancelToken.source() axios..get('get/username', { cancelToken: source.token })
1
2
3
4
5
6解析:
项目的难点 分片上传
Promise.all 收集错误
webpack原理 (.vue, 等怎么转换为js文件)
vue3 composition api怎么实现的
缓存
离线化平台
requestAnimationFrame
10000数据,数据多的时候怎么进行分片处理,不阻塞浏览器进程
输入url到页面渲染 cssdom规范 em-px, 哪些显示哪些不展示