-
Notifications
You must be signed in to change notification settings - Fork 52
有赞面试记录二
今天进行了有赞三面和四面以及HR面,记录下面试官问到的问题
- A. 缓存
- B. 资源合并
- C. 就近访问
我的选择:A、C
面试官问:什么是就近访问?
我的回答:我们知道,网络有很多节点,一个请求走过的节点越多,那么这个请求就越慢,哪怕每个节点都很快,物理距离也会提高网络延时,光速虽然很快,但是传输也是需要时间的
所以CDN解决了就近访问的问题,CDN叫做内容分发网络
,他是一个网络,当我们请求一个资源时,会在最近的节点返回资源(如果有的话),这样就很快
面试官问:什么是缓存?
我的回答:因为请求的资源在CDN上保存了一个副本,这个副本就是缓存,当一个用户请求了一个资源,被CDN节点所缓存,那么另外一个用户也要请求这个资源,CDN会直接把缓存返回。如果CDN缓存过期,那么CDN会去真正的资源服务器去拿资源,这个过程我们称之为「CDN回源」
面试官问:客户端有缓存吗?
我的回答:当然有,浏览器有强缓存和协商缓存(不知道面试官为什么没有针对这个点展开再问)
面试官问:为什么没有资源合并?
我的回答:可能有资源合并,但这属于CDN提供的增值服务,例如example.com/a.js,b.js
通过这种方式,CDN会把两个js文件merge然后返回。有些CDN服务商会提供类似的功能,但是这不属于CDN的标准功能,所以我没有选B
.a {
color: red;
font-size: 20px;
}
.b {
color: antiquewhite;
float: left;
}
.c {
color: aqua;
float: left;
}
.d {
color: blanchedalmond;
}
<div class="a">
aaa
<div class="b">bbb</div>
<div class="c">ccc</div>
<div class="d">ddd</div>
</div>
我的回答:
aaa
dddbbbccc
我的解释:
因为.b
和.c
都浮动了,所以脱离文档流,但是所以两者会新起一行,然后当float元素左边遇到非float元素是会挨着它
正确的答案:
bbbcccaaa
ddd
#id {
color: blue;
}
.a.b {
color: cadetblue;
}
div {
color: chartreuse !important;
}
<div id="d" style="color:red;" class="a b">div</div>
我的回答:!important > 内联 > id > class
面试官接着问,我们常说的优先级算法是,id是100,class是10,tag是1,那么如果我用11个class作为选择器,是否能覆盖id?
我的回答:这个我不确定,以前看过css selector
规范,对算法有详细的描述,不过现在确实忘了
面试官问:比如有十次fetch
调用,其顺序是0,2,3...9
,但是服务端的返回可能是8,0,2,9,10,5...3
,也就是说请求和响应的顺序是不对应的,怎么让其顺序对应起来?
我的回答:在发请求时,在params中添加一个额外的记录顺序的属性sequence
,初始值是0,每次发送sequence++
,发送完毕,会初始化一个长度为sequence
的稀疏数组
然后服务端接收到请求以后,取出params中的sequence
,并原样放入response
中
前端收到返回以后,取出sequence
的值,例如sequence = 5
,那么就把稀疏数组的第5个元素填入response值[ , , , , ,res, , , , ]
等10个请求全部返回,稀疏数组就会被填满,当填满时,在按照顺序执行callback
,把每个res作为参数传给callback
执行
形如:
A | B | C |
---|---|---|
1 | AAA | BBB |
2 | DDD | |
3 | CCC |
当我点击某个单元格时,变为可编辑状态,在样式上体现出来,比如边框加粗等
我的回答:
一个单元格的坐标是(A, 1), (B, 2) 这样
然后可以用二维数组来定义数据结构,但是如何定位一个好的数据结构?让处理、后续的数据merge更方便呢?
我想到两个数据结构,第一个是二维数据[[A, B, C], [1, AAA, BBB], [2, , DDD], [3, CCC, ]]
,然后表格也要做懒加载,因为表格很大,不可能一次性返回所有的数据,比如我左右滚动到了C列,那么后续的列D、E、F...
该怎么加载呢?需要计算下当前所在的行和所在的列,然后把表格右下角的单元格坐标传给服务端,服务端根据算法生成数据:[D: { 1: XXX, 2: YYY... }, E: { 1: null, 2: ZZZ ... }, ...]
如果我上下滚动到第3行,在往下滚动的话,需要加载4、5、6...
等行,把左下角的单元格坐标传递给服务端,服务端根据算法生成数据:[[4, XXX, YYY, ...], [5, null, UUU, ...], ...]
然后把根据服务端下发的数据,进行dom操作,把新生成的dom插入进去即可
我想到的另外一个数据结构是,根据坐标放入一个大数组中,例如[{'A:1' : AAA}, {'A:2' : AAA}, {B:2': XXX}, ...]
,key作为坐标,value作为单元格的值,但是有一个问题,可能会有数据冗余,因为A出现很多次,但是这些都是高度结构化、同构化的数据,gzip压缩率会很高,所以数据体积不是问题
面试官又问:
那么前端应该怎么写?
我的回答:
前端用flex
和table
布局皆可,但是我倾向于用table
布局,因为这个是符合语义化的,excel表,就是一个表格,所以用table是合适的
然后面试官问,那么我如何找到要编辑的单元格呢?
我的回答:
直接根据坐标找即可
面试官又问:
会有什么问题吗?
我的回答:
应该没有
其实后面想想,我应该说的更多一些,比如如何实现单元格的可编辑?editable=true
了解下?这些都是知道的,但是当时没有表达出来
我的回答:
java的面向对象是基于类的,而js的面向对象是基于原型的,那么什么是基于类,什么是基于原型呢?我举一个生活化的例子来说,比如要盖一座大楼,如果有图纸,按照这个图纸来建造的大楼,我们称之为基于类的,图纸就是类,是一个模子,按照这个模子就能实例化一个对象,即大楼。
js是js之父Brendan Eich(布兰登·艾奇),用了10天的时间设计出来的,所以比较糙,面向对象并不是一个标准的实现(即基于类的实现)
那么js基于原型是怎么做的?原型就是,我看到一座楼很好看的大楼,然后按照这座很好看的大楼作为原型新建造一座大楼,那么这个就属于基于原型的面向对象。
当然,以一个大楼作为原型建造的另外一座大楼,如果要深入进去,可能会发现两个大楼有区别,但是js是鸭子类型,我们只关心我们关心的部分,如果两座大楼我们关心的部分,比如都是钢筋混凝土结构,都是两梯四户,内部构造和格局也一样,一些不关心的部分,比如墙体的颜色、用的是LED灯还是白炽灯等我们会忽略掉这些不关心的部分。。所以鸭子类型的意思是,如果一个对象长得像鸭子、走起路来像鸭子、并且会呱呱叫,那么我们认为它就是一只鸭子(其实可能是条狗)
然后面向对象有三大概念封装、继承、多态
,java都有,但是js只有封装、继承
,因为js是弱类型语言,所以没办法使用方法签名来区分函数的重写,所以就没有行为的多态,还是因为没有类型,所以也没有类似于Java中的list list = new ArrayList()
的多态
面试官接着问:
什么是封装?
我的回答:
封装就是把数据和行为封装到一个对象中
面试官又问:
这是你理解的封装吗?
我的回答:
是的
点评:我的回答其实没有错,但是我可以更进一步这样回答:面向对象层面的封装就是这个意思,但是我们编程时,即便不是面向对象也常常用封装这个词,比如一段代码很多地方调用,那么我们常常会说,要把这段代码「封装」起来,这个是另外一个层面的封装了
自己主要在关注js方面,包括架构、项目等问题,css是自己的一个薄弱点,后面要进行专题强化