阿里云OSS前端开发暑期实习一面面经
半个月前师兄内推的简历,昨天下午一面。形式比较简洁,没有hr联系,直接是阿里云的工程师联系的我约的面试。也没有用视频会议,直接电话面试+在线IDE做题。基本上没有问什么八股文,主要是深挖简历,所以问的问题主要都跟简历内容相关。
面试内容
- 自我介绍
问:前端如何检测网络状况,弱网?(看简历里写了做了app弱网模块)
答:网络情况是客户端那边做的,他们判断设备网络波动大,再调我们弱网组件。
问:如果是前端来做,有什么方法?
答:可以设定网络请求最大次数,重复请求超限则判定为弱网。曾经查过navigator.onLine这个属性,但测试发现这个属性没有作用
下来自己查了一下,一般前端监测网络状况有以下几种方案:
(1)window.navigator.onLine属性(布尔值,脱机状态下为false),缺点是有时候结果不准确,会受到其他因素影响。换句话说,就是结果为true也不意味着浏览器能联网。可能电脑上安装的其他虚拟软件会影响这个属性值,如虚拟机,虚拟网卡。我自己测试发现始终都是true的原因在于我电脑上装了Zerotier(虚拟局域网),到控制面板里面禁用之后,navigator.onLine就是正常的值了
(2)window.addEventListener('online', cb),本质上和(1)一样
(3)window.navigator.connection可以拿到网络连接相关的属性,但存在兼容性问题,且测试发现结果相对固定,无法监测实时网络状况
(4)Ajax测速,本质和我的回答类似,使用一个已知大小的文件(可以是图片或者其他文件资源,不需要太大)作为测速源,用img标签的src属性引入,监听onload、onerror事件,或者根据原生ajax请求分别在不同阶段标记时间,用文件大小/时间差得到一个较为模糊的实时网速结果,效果类似于windows中的ping命令
综上所述,通常会采用多种方案组合以达到比较好的监测兼容性和准确性。
3.
问:省市区三级联动的数据是从哪里来的?(简历里写了做了城市相关的配置)
答:用的是npm库里面的element-china-area-data这个包。没有用后端的城市数据,因为结构太复杂了。
问:那意思是会打包到前端工程里咯,省市区三级联动数据量可不小呀
答:当时业务需要只用到了省市两级联动,所以中国600多个市也还好?(自己下来回顾了发现打包时element-china-area-data这个包包含了省市区三级联动的数据,官方给的一个简单的Vue示例打包后足足大小有6.25MB,看来省市区三级联动的数据量还是很大的)
问:好我理解了,客户端那边可能对于打包后的文件体积要求严格一些
4.
问:看你简历上写了微信支付的授权,讲以下微信授权的流程吧?
答:我做的微信的授权分为两类。一类是微信公众号/小程序的登录授权,这种授权很简单,客户端调用微信官方登录API拿到登录凭证code,再拿这个code去微信授权url请求openid就可以了;一类是微信支付的授权,微信支付的流程比较复杂,主要有以下步骤:①前端用户选择商品,商品编号和金额发给后端,后端生成订单告知微信支付系统,返回给前端时间戳、数字签名等支付信息,前端组装信息后拉起微信支付API,用户输入密码完成支付,微信支付系统返回支付状态,前端做对应处理。
5.
问:简历上写了动态计算rem实现多端适配,能讲讲怎么做的吗?
答:rem是相对单位,本质是相对于根元素字体大小。在Vue项目的App.vue中根据UI给出的设计稿尺寸进行动态计算,如当时我们UI给的设计稿一般是750px宽的,我们自己定义的倍率是100,那就是用设备的宽除以750,再乘以100作为根元素字体的大小。后续设计样式全部使用rem替代px。
问:有没有考虑过平板这种横屏的问题,如果都使用rem的话会把宽高都放大,但有些情况是只需要放大宽或者放大高的,这种情况怎么办?
答:我负责的部分好像都是平板竖着用的,至于平板横屏的适配当时是我师傅做的,我没有负责这一块,不好意思,我不太知道
下来自己查了一下,横屏适配一般有如下方法:
(1)媒体查询:
@media screen and (orientation: landscape) { /* 横屏布局样式 */ }
(2)viewport控制页面缩放:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, viewport-fit=cover" />
任何情况下都填满屏幕,且不允许缩放。只能起到初始缩放适配的作用,还需要配合其他方法做适配优化。
(3)js监听屏幕旋转orientationchange事件,再根据orientation状态做两套方案
想起来当时项目里师傅写的有portrait和landscape,猜想应该是对横屏和竖屏做了两套方案,原理应该就是(3)。有两种思路:1.根据高度来设计UI稿件,跟高度绑定后用vh作为单位;2.沿用竖屏的方案,计算当前宽高比和竖屏差多少,整体加一个transform: scale(可以在不同的方向定义不同的缩放值)
6.
问:你知道1px问题吗?
答:听说过,但目前没有遇到过。
问:可以去多了解一些。
对于1px问题,需要先了解几个概念:
- 屏幕尺寸:指屏幕对角线的长度,常说的显示器尺寸24,27,32英寸指的就是对角线长度;
- 分辨率:指宽度和高度上最多能显示的物理像素点个数,常说的显示器/图像/视频分辨率有720p(1280*720),1080p(1920*1080),2K(2560*1440),4K(3840*2160),所以1080p,2K,4K宽高像素点个数是倍的关系,总像素点个数是2倍的关系;
- ppi:pixels per inch,屏幕像素密度,即每英寸聚集的像素点个数,这里的每英寸指的是对角线长度
- dpi:dots per inch,每英寸像素点,用于描述印刷行业的墨点密度,类比ppi
- *dpr:device pixel ratio,设备像素比,指设备物理像素和设备独立像素的比值,也可以理解成一个px的能显示的物理像素点的个数。PC端和早期手机的dpr都是1,即1逻辑像素对应1物理像素
- 物理像素:屏幕显示的最小颗粒,是物理真实存在的,单位是pt
- 逻辑像素:CSS样式代码中定义的像素,是为了使网络资源浏览起来更舒服,也就是让两个屏幕尺寸一样大的设备,呈现的同一个图片看起来差不多是一样大的而发明的
所谓的1px问题,本质就是如何解决不同屏幕上1逻辑像素对应不同比例的物理像素的问题。使用rem作为单位的话需要在初始化rem时就把dpr代入计算。使用vh,vw的百分比单位不会受到影响。
7.
问:看你写了一个OJ平台,在展示用户代码时,前端应该如何防范XSS攻击?如果提交恶意代码嵌入web内容中该怎么办?(OJ前端是React做的)
答:不好意思,我不太知道,可能是跟React的JSX语法有关系?
问:其实是React本身的特性帮助避免了XSS攻击,下来你去了解一下。
对于React中的XSS攻击问题,React的自动转义和JSX语法帮React规避了风险。
- 自动转义:React在渲染HTML和DOM时会对
"'&<>
进行自动转义处理,如<
会被转义成<
, - JSX语法:Babel在编译JSX时会把JSX转化成React.createElement,其中可以防范构造XSS攻击
- ps:在React中使用dangerouslySetInnerHTML是有被XSS攻击的风险的,因为不会走上述流程检查
对于Vue中的XSS攻击,可以使用如下方法规避:
- 使用{{ msg }}插值表达式:Vue像React一样会对其进行自动转义
- 使用CSP:content scurity policy,内容安全策略,可以通过两种方式开启CSP:1.设置HTTP请求header中的Content-Security-Policy字段;2.设置meta标签
<meta http-equiv="Content-Security-Policy">
- 谨慎使用v-html属性:类比dangerouslySetInnerHTML
8.
应用题:
计算localStorage中一个item能存储的最长的字符串长度(计算localStorage最大的存储大小),大致思路如下:
const solution = () => { for(let i=0;i<Number.MAX_VALUE;i+=10) { try { localStorage.setItem('test', new Array(i*1024).join('a')) // 一次性增加1KB的长度,少了浏览器会崩溃 } catch(e) { return i } } } console.log(solution()) // 5120KB -> 5MB
二分查找优化:
const solution = (left, right) => { if(left>=right) return left const mid = left+Math.floor((right-left)/2) try { localStorage.setItem('test', new Array(mid).join('a')) } catch(e) { return solution(left, mid) } return solution(mid+1, right) } console.log(solution(0, Number.MAX_VALUE)) // 5238439B -> 5.1MB
结论:localStorage中最多可以存5MB左右的数据。
第一次写面经,当作自己总结和进步的途径,互相勉励!