大家好,我是若川。持续组织了8个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列
从毕业到现在已经在北京3年了,当年一起来北京的同学,如今都有了要离开的打算。我也在萌生了想要去成都的想法。然而从投递简历开始,就感受到了今年确实不是很景气。很多大厂不是裁员就是锁HC,面试邀约都显得非常宝贵。
HTTPS建立连接过程
http缓存,强缓存时cache-control字符集是什么 publichttps://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control
深拷贝的实现,如果遇到function怎么办 需要判断类型,对于基础类型,直接赋值,对于复杂类型则需要递归处理,并同时设置map,避免嵌套。对于function可以通过 new Function(' return '+ fn.toString())的方式拷贝
webpack 有用过哪些loader、webpack做过哪些优化 loader:babel-loader、ts-loader、style-loader、css-loader、less-loader 优化:提取公共代码、代码分割、代码压缩、按需加载、预加载
微前端的问题,设计思路,有遇到哪些问题,如何做样式隔离。公用路由的设计 采用路由分层的方式,将路由划分为4层,第一层用来区分是iframe还是微应用,第二层用来区分具体的app页面名称由此在配置表中拿到具体的配置信息,第三层为子应用的路由,第4层为子应用的参数。由此实现基座与微应用的路由共享。
样式隔离,一是通过qiankun自身提供的样式沙箱 { sandbox : { experimentalStyleIsolation: true } }
,二是vue组件样式使用scoped,三是顶层样式增加私有类名 面试官反馈说,iframe还是微应用对于用户来说是无感的,配置表区分iframe还是微应用即可,不必多占一层路由
为什么要使用composition-api 首先因为业务性质需要兼容ie所以项目只能使用vue2 通过使用@vue/composition-api方式使用新特性。转变以往的vue选项式开发,为更贴近函数式的代码开发。使原本关联逻辑分散在各个选项中,组件代码庞大的问题的问题得到解决,提高代码易读性、可维护性。同时通过抽取hook实现逻辑复用,提升效率。相较于mixin具有隐式依赖等缺点,更具备可用性。
两数之和https://leetcode-cn.com/problems/two-sum/
纯数字版本号数组排序
function versionSort(versions) {
return versions.sort((a, b) => {
const aArr = a.split(".");
const bArr = b.split(".");
while (aArr.length || bArr.length) {
const A = aArr.shift() || 0;
const B = bArr.shift() || 0;
if (A - B !== 0) {
return A - B;
}
}
});
}
http请求头有哪些字段 Accept系列、Cache-Control、Cookie、Host等等
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers2. 原型链
https://juejin.cn/post/69344983614750720143. 工作中遇到的具有挑战的事情 从零开始搭建完善的工具库,如何组织代码?如何保持资源的动态引入?如何来做单元测试?4. 单页面通信,多页面通信 这个我一下蒙了。但是感觉应该是路由通信、借助cookie、localStorage通信,以及iframe的通过addEventListener和postMessage通信 5. 微前端样式隔离 同上 6. 网络安全展开说 几种安全问题:XXS CSRF、点击嵌套劫持、CDN劫持等 防范主要围绕同源策略,cookie的sameSite 、http-only,referer的验证,CSP等方式来避免https://zhuanlan.zhihu.com/p/83865185
webpack与rollup的区别 webpack大而全,功能全面配置完善,同时loader与plugin非常丰富。并且具有deveServer方便开发调试 rollup小而美,相较没有webpack完善但是同样体积更小速度更快。类似压缩等基础功能也要通过插件实现。更适合做一些工具库的打包处理
介绍一下你写的webpack loader 工具为了兼容vue2、vue3两个版本,核心代码是完全相同的,差异只是在vue特性api的引入上,vue2从@vue/composition-api中引入,vue3从vue中引入.所以loader做的事情就是在构建vue2版本的时候将import { *** } from 'vue'
替换为 import { *** } from '@vue/composition-api'
职业规划 希望在未来的两到三年时间,拓充技术能力的同时,在业务能力上有所沉淀成为业务,形成一定的见解,同时谋求从大头兵向小组长的一个转变
实现具有并发限制的promise.all
function promsieTask(taskList, maxNum) {
return new Promise((resolve, rejuct) => {
let runCount = 0;
let complated = 0;
const taskNum = taskList.length;
const resArr = [];
let current = 0
function handler() {
if(runCount>=maxNum) return
const a = taskNum - complated;
const b = maxNum - runCount
const arr = taskList.splice(0, a>b?b:a);
arr.forEach((task, index) => {
const d = current+index
task
.then(
(res) => {
console.log(current,index,res)
resArr[current] = res;
},
(reason) => {
resArr[current] = reason;
}
)
.finally(() => {
complated++;
runCount--;
if (complated === taskNum) {
resolve(resArr);
}
handler();
});
});
current += taskList.length
}
handler();
});
}
业务相关,聊一下做的印象最深的项目,有哪些关键指标衡量效果,有哪些进步优化空间 这个具体到业务指标原来没有怎么想过,答得不是很好
从具体的业务中讲讲和学习的关系 这个问题也是没有考虑的很好,讲的很虚。是讲的最近做的一个项目的重构,从设计模式的方面,和vue底层的方面讲了一下。后面想想应该从一些新技术或者以前不熟悉的东西入手,讲一边业务开发通过新技术拓展能力,一方面将学习通过实践的方式加深理解
对自我的认知和未来规划 因为问业务相关回答的不是很好,所以着重讲了一下希望加强业务能力
笔试题 合并两个递增链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var mergeTwoLists = function(l1, l2) {
const head = new ListNode()
let current = head
while(l1&&l2){
if(l1.val
毕业以来的工作履历
当时为什么没有走校招
去年换工作的时候收到的offer和选择
有没有收到其他公司的offer,有没有什么倾向性
选择工作有什么着重点
输入一个正整数,输出他的两个素数因子,如没有输出 -1 -1
输入两个数组,分别从两个数组中取出一个元素相加,和作为一个元素,求K个这样的元素的最小和。坐标完全相同,属于同一个元素。
输入一个n*m的多维数组,输出一个字符串,按顺序将字符串中的每一个字符在数组中查找,要求查找位置必须相邻,且每一个元素只能使用一次。输出字符串在数组中的坐标 牛客网的测试用例无法调试,只知道通过率分别是100%,95%,95%.实在想不出边界条件了。这里就不放出代码误导大家了。
http 请求头有哪些关键字,反映客户端信息的是那个字段 同上 User-Agent
http请求触发catch的原因可能有哪些 拦截器捕获其他异常,比如204,请求处理函数执行异常,返回资源异常(不符合接口定义)
302、304什么含义 302:临时重定向 304:资源未修改,使用缓存
项目重构前是什么状态 部门内第一个是使用组合式模式开发落地的项目,由于前期不熟悉缺乏经验。导致项目数据流动混乱、功能杂糅、请求相互依赖,不但没有突出组合式逻辑清晰代码复用的优点,反而导致代码可维护性差,白屏时间长。通过梳理逻辑功能,重新组织页面、组件,按照单一原则抽离hook,解耦无关逻辑。梳理数据流动,无关请求并行触发。提升代码可维护性,加快首屏渲染。
微前端的技术方案是怎么确定的,有没有遇到什么问题,样式隔离,数据管理,路由冲突
是主要由我决定的。采用qiankun的原因,一是方案成熟,文档健全,社区案例多。二是我自身以前有过一些经验,对qiankun比较了解,能够快速落地
样式隔离,一是通过qiankun自身提供的样式沙箱 { sandbox : { experimentalStyleIsolation: true } }
,二是vue组件样式使用scoped,三是顶层样式增加私有类名
数据管理,qiankun本身有提供globalState相关api,但是子应用只能在onchange事件触发时才能拿到公共数据。所以先声明公共数据,通过initGlobalState注册,然后在微应用注册阶段通过props方式预先传递给子应用。在子应用侧,通过mounted钩子和onClobalStateChange共同维护公共数据
路由冲突,子应用是需要与基座共享路由的,所以在路由激活子应用的模式下。预先分配给子应用一个激活路由,这个路由同时也是子应用的baseRoute,在挂载阶段通过props传递,子应用拿到baseRoute作为前缀注册路由。从而实现路由共享。
qiankun的打包配置
https://qiankun.umijs.org/zh/guide2. 了解市面上其他的微前端方案么 1、是类似乾坤、飞冰这种基于singleSpa的方案 2、是类似美团那种,相同技术架构的,自研原生实现 3. 为什么使用Monorepo组织代码仓库 我们这个库,设计上就是要能够支持vue2、vue3两个版本,以及不同业务需要的 采用Monorepo组织代码仓库,方便管理维护不同的功能包、既做到了独立发布,又能在项目中统一维护 4. webpack知道有哪些插件lodaer么?5. webpack你知道哪些优化
构建阶段、多线程、缓存
资源产物 代码压缩、代码分割、提取公共代码、懒加载、预加载
leetcode 452题
https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/
http1 和http2的区别 压缩请求头,二进制分帧、多路复用
https://zhuanlan.zhihu.com/p/1025610342. 讲一下loader和plugin webpack的loader主要用来处理特定的文件,进行转换 plugin通过wepack提供的构建钩子可以实现loader无法实现的功能,比如deveServer、代码分割等 3. extenral 通过extenrals
选项,可以将依赖从输出的bundle中移除,并保持资源引入 4. 讲一下微前端 微前端并不是为了取代iframe,他们都有所适用的场景。对于部分相互独立并没有什么复杂数据交互的项目来说iframe就很合适,而且天生具备很好的隔离。而对于具有数据交互,尤其是在一个大项目中拆解出不同的业务功能模块来说,微前端的模式更合适。5. vue2和vue3的响应式 vue2的响应式是基于Object.definePropert
数据劫持与数组常用方法的改写来实现的。对于复杂数据类型,需要层层递归劫持,性能较差 vue3是通过原生api proxy
代理实现的,不需要递归,也不需要改写方法,性能更好,支持更好。但是由于代理只是对目标对象,在传递响应式对象时,操作不当容易丢失响应性。6. 讲一下es6 这个就是老生常谈了,大家仁者见仁智者见智 7. promise、promise.all ,promise与async await的区别,async await如并发 promise 8. 计算岛屿周长
// 给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。
// 网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
// 岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
// 示例1:输入:grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
// 输出:16
// 解释:它的周长是上面图片中的 16 个黄色的边
// 示例2:输入:grid = [[1]]
// 输出:4
function search(grid) {
let res = 0
grid.forEach((line, i) => {
line.forEach((item, j) => {
if (item === 1) {
dp(i, j)
}
})
});
function dp(i, j) {
if (i == 0 || grid[i - 1][j] == 0) {
res++
}
if (i + 1 == grid.length || grid[i + 1][j] == 0) {
res++
}
if (j == 0 || grid[i][j - 1] == 0) {
res++
}
if (j + 1 == grid[0][1].length || grid[i][j + 1] == 0) {
res++
}
}
return res
}
const grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
console.log(search(grid))
这一面就是简单沟通了一下现在的工作情况。电话面试大概10分钟就结束了
http 缓存cache-control字符集 max-age\public\private\no-cache\no-store\
网络安全,页面出现广告什么原因 XSS脚本添加页面?页面劫持、代理?CDN,iframe嵌套 同上
微前端样式隔离,js隔离原理 同上
babel原理
loader和plugin的区别 同上
map和object的区别 map补足了js没有这种字典类似功能的短板。虽然好像map能做的key/value object也可以实现。但是map可以按照顺序递归,key可以是对象等复杂数据类型
Object.assgin 与 ...复制对象的区别 这个除了使用方式上,并没有感觉有什么不同,之后尝试了一下表现也是一样的
有做过组件库,或者这种公共基础么?有考虑哪些设计原则 单一原则、拓展性、可靠性
有用过哪些ide的能力(变更函数名?) 这个没懂是想问什么
尾递归优化 这个是从调用栈的角度来讲的,通过尾递归优化的方式,释放中间变量
https://zhuanlan.zhihu.com/p/39371113411. ts 用过那些函数,interface和type的区别 interface 可以拓展 extends interface能够声明合并 type不可以extends、implement但是可以类型交叉 type可以声明类型别名、联合类型、元组 interface不可以 12. 扁平化嵌套数组有几种方式
flat
toString().split(',')
递归
你最近做的事情 在做一个lowCode平台的代码重构,项目采用vue3但是之前是组合式的写法。我们重构主要做了两件事,一是将选项式改为组合式,并抽离hook;二是将整个渲染配置数据从组件中剥离出来,通过响应式的方式构建单项数据流维护
介绍数据流,是否了解市面上其他公共状态管理工具 ,了解Piniahttps://pinia.vuejs.org/introduction.html#basic-example通过vue3提供的响应式api,我们获得了无需借助第三方工具,即可实现公共响应式数据的维护。我们总结了一些经验,可以直接定义响应式数据,以及更新他的set方法通过代码引入,props传递以及porvide/inject的方式灵活使用。感觉这部分表达为什么不用市面上已有的状态管理库而用我们的方案,这部分讲的不够自信,理由不够充分
展开问业务
问微前端的选型原因 一是qiankun的技术方案相对比较完善,无论是常见问题还是社区经验都比较丰富 二是我个人之前有一定的知识储备,使用qiankun能够容易落地
如何寻找到两个dom节点的最近公共父节点 通过从下向上递归,并将父节点储存,比较
美团二面感觉面的不是很好二面之后就没有后续了
················· 若川简介 ·················
你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经坚持写了8年,点击查看年度总结。
同时,最近组织了源码共读活动,帮助3000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。
扫码加我微信 ruochuan02、拉你进源码共读群
今日话题
目前建有江西|湖南|湖北 籍 前端群,想进群的可以加我微信 ruochuan12 进群。分享、收藏、点赞、在看我的文章就是对我最大的支持~