更多面试内容,可查看我的面试记录专栏
以下答案为面试后整理,并非面试中的回答。
一面
状态:通过
1. 自我介绍
你好,我是XX,我现在在XX主要负责XX小程序,主要做负责相关的功能的迭代,以及线上小程序线上性能的提升。
从去年X月开始负责的小程序,从负责到现在,小程序的FMP从xxms降至800ms左右,到达率从xx%提升至xx,白屏从0.22降至0.18。
在X月之前,主要负责XX相关业务,负责的内容有 XXX、XXX、XXX。其中比较重要的项目有XX机制的升级,影响XXX业务。以及 xx业务的 xxxx项目,有上亿的流量,最后 XX 收益约占总收益的三分之一
2. 根据自我介绍了问了 小程序性能优化的细节
性能检查清单 性能优化主要有6个方面:
1.优化小程序包
- 优化逻辑层层js代码体积,如合理的封装组件,删除无用代码,合理划分组件等
- 提升最低基础库版本以接入多种包优化方式。例如小程序在3.270.0才支持的生命周期onPrefetch
2.提前核心请求发送时机
- 检查所有核心页面的request是从那个生命周期发出的,如果发出核心request的生命周期,执行时间小雨250ms。例如:xx小程序通过性能时序图可知,在将核心请求提前至onPrefetch生命周期后,核心请求发出大约在88ms左右。
- 减少异步端能力/Promise的使用以尽快发出请求。保存端能力返回的结果,例如:用户的定位信息,用户系统的信息
- 避免发出多次核心request。页面fmp仅出发一次核心request
- 延后首屏渲染非必要request。例如:在xxx详情页中,就有两个接口,一个接口是获取 主体信息,一个接口是获取评论数据,我们是可以将获取评论这个接口,等首屏渲染完成后再发出。
3. 优化核心请求服务器响应时长
- 优化核心请求服务器响应时长。这个是需要根据现有请求耗时,评估出需要优化的接口(根据现有耗时、流量、成本),推动后端同学进行优化
- 配置prelink以加速网络请求
- 服务端开始gzip
4. 优化首屏渲染
- 按需渲染,检查核心setData渲染的非可视区域显示内容/显示屏幕时图体积的比例来判断状态
- 避免在fmp前频繁调用setData。如果setData次数少于3则为通过
- 避免长时间处理请求数据。核心请求结束到核心setData的调用时间间隔,小于15ms,为通过
5. 避免不必要的swan API/console调用
- 避免重复swan API调用,评判标准重复调用swan API的同步累积耗时小雨10ms,则通过,大于20ms,为优先,大于50ms为高优。重复调用用swan API的判断标准是:500ms内,调用相同的API,函数参数与返回参数完全一致。
- 避免console。线上尽可能不要使用console 前端性能优化篇之console.log
6. 优化图片使用
- fmp前,不在可视区域的图片均开始lazy-load属性
- 避免请求过大的图片。页面中所有图片的宽高乘积小于实际显示宽高乘积 * (设备像素比 ^ 2)
- 防止页面抖动,fmp前,页面中的图片宽高适中保持不变
3. 小程序的架构是什么样子的,有了解过微信小程序或者其他小程序吗?
先简单介绍一下小程序的开发流程
- 首先我们用swan写布局
- 接着通过开发者工具打包,上传到我们的小程序到B端服务器,(如果是内部,我还是通过流水线进行上线发布的)
- 最后小程序的审核流程,有机审、人审
- 最后是用户点击小程序时,客服端请求小程序C段服务器,C端服务器再从B端服务器获取小程序包,整个过程都是加密传输,可以保证代码的安全。
SWAN
智能小程序的框架,命名为SWAN。自上而下分层结构如下:
- 第一层是开发者基础库,命名为swan-js,开发者直接和这层打交道。swan-js负责两件事:(1) swan代码转换为HTML,变成webView可运行机制(2) 客户端端能力的封装暴露
- 第二层层是swan-native。这里面最核心的是API和组件NA实现。其中双栈管理也在这一层,另外Extension用于开发者宿主自身能力扩展使用。
- 第三层这层为Porting-layer。这层是小程序为了实现开源,增加的一层与宿主的接口层。
- 最下层是宿主的基础能力层。如果宿主没有这些能力。可以参考我们公司开源的示例,可直接集成到宿主使用
4. 算法题
function countAndSay(n) {
let arr = ['1', '11'];
if(n <= arr.length) {
return arr[n - 1];
}
let i = 1;
while(!arr[n - 1]) {
let pre = arr[i];
let item = '';
let count = 1;
let cur = pre[0];
for(let j = 1; j <= pre.length; j++) {
let next = pre[j];
if(cur !== next) {
item += count + cur;
cur = next;
count = 1;
}
else {
count++;
}
}
i++;
arr.push(item);
}
return arr[n - 1];
}
5. VUE数据双向绑定的原理
Vue 内部通过 Object.defineProperty
方法属性拦截的方式,把 data
对象里每个数据的读写转化成 getter
/setter
,当数据变化时通知视图更新
更多详细解答:0 到 1 掌握:Vue 核心之数据双向绑定
6. FLEX的基础知识,flex-shrink,flex-grow,flex-basis
flex-shrink:当空间不足以展示的时候,是否被压缩
flex-grow:当内容超过既定的空间,是否放大
flex-basis:压缩和方法的基准,没设置的时候为width的值
Flex 弹性布局
7. 如何实现一个FLEX相同功能
暂时没找到答案,后续完善
8. 为什么离职,对下一份工作的期望,问了我觉得什么样工作是我觉得有挑战的
离职原因:
- 现在的工作过于重复,希望进一步的提升自己
- 我喜欢更有挑战的工作
什么是有挑战的工作?
更想做一些基础的插件的封装
有了解过可视化方面吗?
有,自己忙完这段时间,也有这方面学习的计划
二面(20220321)
面试官是一个非常nice的小姐姐
状态:未通过
项目
写一个once修饰器
vue中key的作用
Vue中 key 值的作用
vue中key的作用和工作原理
为什么 Vue 中不要用 index 作为 key?(diff 算法详解
vue中如何隐藏一个元素
v-show: 会渲染dom,display:none
v-if:惰性渲染,条件为false时,不会渲染dom,成本更高
CSS怎么隐藏一个元素,对回流和重绘的隐藏,对事件响应机制的影响
更详细分析,可以查看五种方法隐藏元素,成本消耗以及对事件的影响
方式 | 回流 | 重绘 | 事件响应的影响 |
---|---|---|---|
visible: hidden | 否 | 是 | 无法点击 |
opacity: 0 | 否 | 是 | 可以点击 |
display: none | 是 | 是 | 无法点击,可以模拟点击 |
z-index利用层叠上下问隐藏dom | 是 | 是 | 无法点击 |
position 定位在可视范围之外 | 是 | 是 | 无法点击 |
如何隐藏父元素,子元素显示
- 父 visibility hidden 子visibility visible
- 父定位(position)定位到可视范围之外,子元素再定位回可视范围
如何垂直居中一个元素
- postion + margin
- postion + transform
- flex
- 单行文本元素line-height
输入url到页面渲染
- 浏览器进程的UI线程捕获到用户输入的url,并调用网络线程
- 网络线程进行域名解析(DNS),获取到ip地址,并判断是否为安全网址(safebrowsing)
- 若是安全网址,继续建立连接(TCP),拿到服务端返回的数据,并发数据传给UI线程
- UI线程,调用渲染器进程,通过IPC通过把数据传递给渲染器进程
- 渲染线程 DOM、CSSOM、Layout tree、layer tree和绘制样式表、栅格化、合成器帧
- 合成器帧传给浏览器进程,浏览器使用GPU绘制
Event Loop
setTimeout(() => {
console.log(1);
}, 0);
new Promise((resolve) => {
console.log(2);
resolve(3)
}).then(res => {
console.log(res);
});
async function foo() {
console.log(4);
};
(async () => {
await foo();
console.log(5);
})();
答案:2 4 3 5 1
算法,获取连续子数组最大和
function sum(arr) {
if(arr.length === 0) {
return {
max: 0,
resArr: [];
}
}
let max = arr[0];
let resAee = [arr[0]];
let start = 0, end = 1;
let temp = max;
for(let i = 1; i < arr.length; i++) {
if(temp + arr[i] > 0) {
temp += arr[i];
}
else {
temp = arr[i];
start = i + 1;
end++;
}
if(max < temp) {
max = temp;
resArr = arr.slice(start, end);
}
}
return { max, resArr };
}
写在最后
祝大家面试顺利,拿到满意的offer,更多面试题关注我的面试记录专题。有什么疑问欢迎评论