阿里影业
一面(11分钟):
面试官:你好,我是阿里影业的,这边由我对你进行一下面试,面试时间大概在20分钟,请问你方便吗?
我:稍等,我走出来下(上班上到一半突然被电话面试,真是出其不意),嗯,好了,可以开始了。
面试官:不使用任何框架实现给dom节点加一个类名?
我:dom节点有一个classList属性,这个属性有一个add方法,直接给dom节点添加一个类名就行。
面试官:那classList有兼容问题,怎么处理呢?
我:如果要考虑兼容问题的话,我们可以用dom节点的另一个方法setAttribute,先获取dom节点的class属性,通过getAttribute(‘class’),然后用indexOf把对应的类名判断下是否存在,如果存在,则不用再添加,如果不存在直接在获取的类名字符串后加一个类名,再setAttribute进去。
面试官:你刚才说的indexOf它对于匹配abc,和ab都是可以匹配上的,怎么处理呢?
我:如果要考虑严谨的话,我们可以用split把getAttribute(‘class’)进行分割,然后将每个分割的值trim后,去和你的类名比较,如果存在的话就不再添加类名,这样就可以处理indexOf匹配abc和ab问题了。
面试官:如何对一个字符串数组去重?
我:可以声明一个空对象,和声明一个空数组,然后遍历这个字符串,将遍历到的字符串的值存到空对象内作为对象的key,然后值为true,然后插入到新数组中,数组接着遍历,如果对象的key值已经有这个key了,就不插入新数组中,最后返回数组。
面试官:如何随机输出一个5-10的数字。
我:随机数可以用Math.random()输出一个0~1的数值,然后用这个数字乘以十,取整,然后除以二(忘了说再加五了)就可以满足你说的结果了。
面试官:讲下简单请求。
我:简单请求就是我们平时请求看到的接口请求,没有进行options请求。而预检请求就是你说的非简单请求会进行一次options。
面试官:那你讲讲怎么样才会触发非简单请求呢?
我:请求头中出现超过两个类型的时候就会触发预检请求。(这个回答应该是错的,后面我查了,满足下面的所有条件就不会产生预检请求,也就是该请求是简单请求:
不会产生预检请求。具体来说如下
**请求方法是GET
、POST
、HEAD
其中任意一个;
**必须是下面定义对CORS安全的首部字段集合,不能是集合之外的其他首部字段。
- Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport-Width、Width。
- Content-Type的值必须是
text/plain
、multipart/form-data
、application/x-www-form-urlencoded
中任意一个值
面试官:再问你几个问题吧,你正常是用display:flex吧。
我:对的。
面试官:rem有用过吗?
我:rem和em一个是基于根节点成比例换算,一个是根据父节点成比例换算,而rem是根据html的font-size做比例换算。
面试官:那rem是怎么做移动端响应式的呢?你主要讲下核心就行。
我:首先设置一下html根节点的font-size,然后根据浏览器缩放,动态换算html的font-size大小,这样html子元素们有设置的rem就会实时换算,从而达到响应式兼容。
面试官:如果浏览器大小改变了,根节点的font-size会改变吗?
我:会改变的。这边等了5秒所有,我继续作答,如果不想改变也可以,我之前有处理过在不同设备的时候,会给font-size在屏幕大小范围内设置固定的font-size,这个可以处理对于一些设备的1px和0.5px像素问题。
面试官:flex有几个属性。
我:平时都是用flex:1,它有几个属性倒不是很清楚(后面查了有flex-grow、flex-shrink、flex-basis)。
面试官:那你知道flex-grow、flex-shrink吗?
我:flex-shrink我平时用都是设置为0,表示不被挤压,flex-grow用的比较少(其实就是不懂,并且常常都在用~很气自己基础不够扎实)。
面试官:讲讲你平时有什么技术沉淀呢?
我:我封装了一个element-form组件的npm包,之前周下载量最高可达2000。
面试官:这个在你简历上好像没体现呀!
我:嗯,现在因为目前公司都是内网,就没什么时间去更新那个npm包了,所以下载量没那么多了,就不大好意思写在简历上。
面试官:那我们今天的面试就到这,如果有下一轮会再通知你。
我:好的,拜拜。
二面(30分钟):
1.设计模型
2.作用域链
3.设计模式、设计原则
4.兼容性
5.BFC
6.函数式编程
7.什么事件不能冒泡
8.如何学习
京东
一面总结(90分钟):
1.自我介绍环节
2.讲下vue传值有几种方式
3.讲下vue2和vue3有什么区别
4.this.$message如何实现的,讲下原理
5.instanceof是如何做比对的
6.如何实现一个订阅模式
7.观察者和订阅发布的区别
8.什么是委托,他有什么优点
9.讲讲数组怎么去重
10.webpack中的hash、chunkhash、contentChunk有什么区别
11.你都做过哪些webpack优化
12.讲下路由hash和history的区别
13.讲下路由权限如何控制
14.bind、call是如何做到this指向的
15.vue中的v-for中的key作用是什么?key如果用index会有什么问题?
16.讲下js中的event loop
17.watch和computed哪个性能更好
18.vue组件销毁你都做了什么
19.vue平时用到哪些钩子函数
20.如何自己封装组件,饿了么组件所有属性如何继承,所有事件如何也都继承呢?
21.babel中的preset-env和pollyfill有什么区别
22.了解过微前端吗?
23.用过node吗?
24.配过nginx吗?
25.遇到过什么问题?
26.webpack中如何排除cdn库
微盟
一面:(用时1小时5分钟-腾讯会议语音)
面试官:请问你是叫某某某吗?
我:对的。
面试官:我先问两个问题,你用什么技术栈,是做to B还是 to C多一些?
我:vue,to B。
面试官:嗯,那我们开始正式进入面试环节;以下是我们面试的整个流程:
1.css
2.js
3.网络&安全
4.框架
5.工程化
我们总时间大概在一个小时左右。
我:好的。
面试官:那请做下简单的自我介绍开始。
我:好的,那我开始做一下自我介绍,你好,我叫某某某,今年多少岁了,目前就职于某某公司,主要负责balabalabala…..
css方向:
面试官:请回答下盒子模式是什么?
我:盒子模式分为标准模式下和怪异模式下,首先标准模式下盒子模型包括外面距、边框、内边距、内容;怪异模式下的盒子模型包括外边距,内容(边框和内边距和内容)。
面试官:那什么场景会需要用到怪异模式?
我:balabalabala…心想不就是ie才会出现怪异模式吗?还有啥场景可以用怪异模式呢?边框融合?
面试官:什么是BFC?
我:BFC、BFC、BFC念了三遍,想不起来了。心里想才问第二个问题就不行了,脑袋一片空白。
面试官:从css的角度有什么可以优化的?
我:减少重排重绘。
面试官:怎么做?
我:开启3d渲染引擎,加速gpu渲染。
面试官:那也是一个方法,说下遮罩,讲讲层级是什么逻辑。
我:z-index设置显示级别?
面试官:就只有z-index吗?
我:还有层级约束,同级层级中,其中内部层级无法超越父级层级的z-index。
JS方向:
面试官:let、const分别是什么?
我:let变量声明,为什么会有let,因为之前var是全局声明变量,let主要用于块级作用域变量声明。
面试官:我们时间不够,请直接回答问题。不要讲历史!
我:好的,const是声明常量,一旦声明了就不能修改。
面试官:那const声明一个对象呢?
我:引用类型是可以修改的。
面试官:那有什么办法可以让引用类型不可以修改呢?
我:可以用Object.defineproperty中第三个参数里面有一个可写属性,设置为false就行。
面试官:还有其他办法吗?
我:还有可以把对象冻住。
面试官:如何实现一个深拷贝?
我:深拷贝主要实现是判断当前是否是一个引用类型,如果是引用类型的话就递归拷贝下,如果不是就直接复制。
面试官:你有用过Promise.all吗?
我:用的比较少(心里想没用过,但是又不能直接说),大概了解怎么用。
面试官:那它是什么逻辑?
我:Promise.all接受一个数组,数组每一项都是一个Promise,返回值是所有的Promise都执行成功最后输出才是成功。
面试官:如果让你自己实现一个Promise.all你会怎么实现?
我:我忘记了Promise源码是怎么写的了。但是我有一个实现的思路,首先知道它的入参是一个数组,那就可以知道数组的长度,然后遍历所有的Promise并去执行,直到Promise执行有结果时去调用同一个获取当前所有状态集的方法来判断当前是否都执行成功或有执行失败的,最后输出所有执行的Promise的执行状态集合。
面试官:你怎么判断当前执行的是哪一个Promise?
我:用数组的索引。
面试官:解释下bind,call,apply区别。
我:bind是绑定谁this就指向谁,bind就一个参数。
面试官:不对,bind不止一个参数。
我:call和apply的执行是一样的,唯一区别就是参数不一样。
面试官:那bind可以无线bind下去吗?
我:应该可以吧。
面试官:说说箭头函数都有什么特征。
我:箭头函数是匿名函数,箭头函数的this来自它的父级。
面试官:那可以bind(箭头函数)吗?
我:停顿3秒…不行吧。
面试官:如何判断数值类型,都有什么方法?
我:typeof, instanceof , 比较严格的方式Object.prototype.toString.call(target)。
面试官:讲讲Event Loop.
我:停顿2秒…给点提示。
面试官:就是宏任务、微任务那些。
我:那就是普通任务执行,遇到宏任务执行第一个宏任务后,会把第一个微任务收掉再执行下一个宏任务接着又执行下一个微任务。注(这边正确逻辑应该是普通任务都走完,然后收掉第一波微任务,再走下一个宏任务,接着走第二波任务以此循环)
面试官:那setTimeout(()=>{5个Promise.resolve()})的执行顺序是什么?
我:5个按顺序执行。
面试官:那递归这个计时器呢?是怎么执行的?分层还是一口气执行呢?
我:分层执行。
网络&安全方向:
面试官:同源策略是什么?如何处理跨域?
我:协议、域名、端口有其中一个不一样就不是同一个源;vue可以针对普通请求设置跨域为true,就可以对普通跨域进行请求。
面试官:vue有这种能力?
我:不对不对,那不是vue干的事。我还是先讲服务端的吧,服务端可以开启跨域,有一个cre(withCredential)…的属性开启来就可以处理普通跨域请求,还有复杂请求的话我记得是要开启2个属性就行,还有一个就是服务端针对ip作为白名单就可以解决跨域问题。
面试官:常见的状态码都有哪些?
我:200、404、500、401、403。
面试官:304是什么?
我:重定向?
面试官:不对。
我:缓存?
面试官:对的,什么缓存?
我:协商缓存。
面试官:讲下http中对称加密,非对称加密,数字签名都是为谁加密?
我:一脸懵逼…它们都是为谁加密???我讲讲它们都是什么,我的理解,安全我最近也在做,首先对称加密我用到的是AES,前后端用同一个key加解密;非对称加密一个是公私钥,公钥可以解私钥,私钥可以解公钥;数字签名我理解它应该是和加盐差不多。
框架方向:
面试官:如何知道dom渲染完成?
我:mounted。
面试官:解释下vue2和vue3监听对象的区别,并说下优缺点。
我:vue2用到的是Object.defineproperty来劫持每一个key,通用他们的getter和setter来订阅值的变化,而vue3用到的是proxy代理,又因为vue2不能对引用类型友好的进行劫持,所有尤大大重写了引用类型的劫持方法。vue2劫持的缺点还有一个是不好扩展,每增加一个都要递归来监听,而vue3的代理就不用,你只要监听最上层的对象就行。
面试官:那你说下装饰器和代理的区别?
我:这个…,我回答不上来。
面试官:vue传值都有哪些方法?
我:应该有9种方法,我可能说不全。
面试官:不用全都讲,只要讲一些常用的就行。
我:props、v-bind、emit、provide、inject, vuex(还有$parent,eventBus,localstoryge,sessionStoryge,$children,手动写一个定阅等等)。
面试官:讲下keep-alive是什么?
我:它是一个组件缓存,当你的组件被缓存时并隐藏了,再次被激活时它会走组件的activited钩子,表示命中了该组件。
面试官:那如果组件带有参数呢?如何缓存?
我:keep-alive它有一个属性可以匹配全路径缓存。
面试官:keep-alive是怎么实现的?它是缓存代码片段,还是虚拟dom,还是分片段?
我:balabalabala… 虚拟dom。
面试官:DSL如何做到级联?
我:表单项A联动表单项B,我们是将联动的逻辑放到表单项B的配置中的,B如果联动C那联动逻辑可以写到C的配置中。
面试官:表单如何统一实现校验方法?
我:我是给每个表单项都支持校验方法,然后向表单发通知,由表单来收集所有检验来实现的。
工程化方向:
面试官:你们工程化是什么?
我:webpack。
面试官:你有手写过webpack配置过吗?
我:没有,但是大致都知道什么意思·。
面试官:假设你是项目负责人,你要怎么考虑包太大,编译慢的原因和如何处理?
我:包大就分包,webpack一开始什么都没做的打包方案是将所有js打包到一个js文件中,如果我们用懒加载就可以做到分包效果,可以将一些相同的代码合并,采用tree shaking。
面试官:如何开启tree shaking?
我:安装插件和配置就行,它是一个静态语法分析,直接可以分析你的静态代码。
面试官:继续。
我:编译慢的话可以采用异步编译。balabalabala……这边聊到优化去了..偏题了。
面试官:时间有点超时了,最后一个问题,你们项目中有用到ts吗?
我:没有。
面试官:那我们今天的面试就到这里结束了。
我:我还想再补充下刚才那个问题,虽然我们项目中没用到ts,但是我自己的项目是用ts的。
面试官:其实没那么硬性要求,ts是一个…
我:好的,谢谢,88
面试官:拜拜
二面:(用时1小时5分钟-腾讯会议视频)
巧了,二面的面试时间和一面是一样的。
面试官:你是叫某某吗?
我:不是,我叫某某某。
面试官:不好意思。
我:没关系。
面试官:那我们今天的面试正式开始,你先做个简单的自我介绍。
我:好的,那我开始自我介绍了。balabalabal…
面试官:你刚才讲到你的项目,那你讲讲你是怎么实现的。
我:DSL…..balbalabalabal应该有讲8分钟左右。
面试官:如何把一个三维的数组拉平,再去重,再将序。
我:首先可以使用数组的flat方法,将数组进行两次flat后,它就拉平了。
面试官:为什么要两次呢?请问flat的参数是什么?
我:我暂时不清楚flat的参数,那我先讲下去重吧,假设已经用flat把三维数组拉平了,接着去重的话,如果是简单的数字数组的话,那我们可以用[…new Set(Array)],进行去重,如果是比较复杂的话,我们可以遍历数组,然后将数组的每一项作为一个对象的key,以及用一个空数组来计入这个去重过的数组,如果遍历到同一个key项去和刚才的object中的key做对比,如果存在不做处理,程序继续,直到所有遍历结束就可以得出一个去重数组;接着我们对数组做降序,我们可以用sort方法,也可以自己用分治算法写一个降序函数。
面试官:如何用分治算法写一个降序呢?
我:分治算法的原理是,遍历数组每一项,然后把当前项的比他大的放左边,比它小的放右边。
面试官:那你这样和sort差在哪里?
我:分治算法的复杂度是在OnLogn,我记得sort的复杂的是On^2,主要是遍历过的那个数值只要比较一轮,下轮比较的时候就不需要再对他进行比较了。
面试官:vue中的diff是如何实现的,请说下头比较,尾比较,同层比较。
我:这…我还没看到vue中diff的源码这一部分,但是我知道diff是什么一个逻辑。
面试官:vue中diff是根据遍历虚拟dom,然后去遍历所有虚拟节点判断节点元素对应的dom type,以及给他设定一个key值,如果下次比较的时候,这个key值变了就表示这个节点需要做更新,所以我们在写v-for的时候写那个key它是可以提高比较性能的。balabalabal…应该讲了有五分钟(面试官还是挺好的,帮我解释了一下)
我:嗯,懂了(其实还没全懂)。
面试官:讲讲vue路由的原理。
我:vue路由分为两种形式,一种是hash,一种是history;首先讲下hash,它是根据路径上的#后面的变量来控制路由跳转的,而history是根据h5的pushState来进行路由跳转的,它俩的效果是一样的,但是hash会在路由上多一个#以及后面的变量。
面试官:hash是怎么监听变化的?
我:我记得有一个好像是onHashchange可以监听。
面试官:现在不是比较流行的有按需加载,那按需加载就会出现webpack把一个js文件拆分成多个js文件,那请求路由是怎么知道对应的js在哪一个文件呢?
我:停顿8秒左右,我对路由源码还不是很清楚,会后我会去看下vue-router源码,虽然我不知道它源码怎么写的,但是我好像记得它是给js文件名加上了hash值,这样路由跳转的时候就可以根据这个hash值做跳转了。
面试官:webpack如何做优化,都做过哪一些呢?例如有写过css loader吗?
我:没做过什么优化,但是我对他的优化方案还是有一些了解的,例如,压缩。
面试官:压缩本身就自带了。
我:我说的是uglify。
面试官:那你讲讲你知道的。
我:tree shaking,静态语法分析;代码重复合并,可以控制代码重复几次时就让它合并生成一个新函数来打包。
面试官:那请问如何设置合并代码呢?
我:我一时想不起来怎么设置了,只记得有一个插件里面有一个属性可以设置。
面试官:还有什么优化方案吗?
我:dllplugin,我知道这个,但是我还没用过。
面试官:dllplugin可以将只更新的js打包一块,将未更新的打包一块,这样我们再更新cdn的时候就只更新被更新过的就行。
我:嗯,下次我试用用看。
面试官:讲讲什么是虚拟列表,项目中有用过吗?
我:项目中还没有用过,因为还没有遇到过这样的业务场景,但是大致明白它是一个什么原理。虚拟列表是根据浏览器的可视屏加上滚动距离来判断当前滚动的位置。假设我们一屏有十条数据,那我们可以设置一个数组,里面放10条数据,当我们滚动后,根据滚动的距离判断当前要显示的数据。
面试官:那你这样肯定会出现抖动。
我:那我们渲染三屏数据应该就可以不抖动了。
面试官:其实可以设置三屏或四屏数据,给未显示的做一个骨骼架,这样就不会抖动了。
我:那我想问下,每条数据的高度是一致的吗?
面试官:有一致的也有不一致的。
我:那假设初始页面是在第10屏幕,鼠标向上滚动,数据的上上屏动态加载出来,那它就不算抖动吗?
面试官:这个抖动是允许的,如果是正常从第一屏滚下来,是没问题的,如果是从中间往上滚一定会出现数据高度不确定导致页面撑开的现象。
我:明白了。
面试官:讲讲继承。
我:现在用的比较多的是es6的extend继承,还有es5的继承是寄生式组合继承,它是从寄生继承,和组合继承演变过来的。还有es6或更高版本推荐用extend,所以我现在有用比较多的是这个,它也是一个趋势。
面试官:你们项目中都用到什么设计模式。
我:我们项目中用到的设计模式比较少,如果说要用到应该是vue用到的观察者模式。
面试官:你自己封装组件的话没用到过单例和工厂吗?例如组件用工厂来封装,这样可以比较好的扩展。
我:我封装的那个严格来说应该没有用到工厂,但是我也支持用户自己做扩展,只是它不能任意做扩展。
面试官:我看到你拿笔了,你就手写一个防抖或节流,随便写一个拿给我看。
我:好的,稍等。
…..5分钟过去了….,看到了吗?
面试官:你怎么没用到setTimeout。
我:我可能把防抖和节流搞混了,你说的用到setTimeout那个是在一定时间进到函数的时候会清除setTimout,然后直到一段时间后都没有再进到函数是,间隔一定时间去执行对应操作,我写的这个它的场景是按钮提交的时候防止它多次提交时,假设我设置一个按钮300毫秒内只能点击一次这样的一个场景。
面试官:你对我们的公司有什么想问的吗?
我:balablablaba….
面试官:dadadada…….
来回两三回合…
我:暂时没什么问题了。
面试官:那今天的面试就到这里了。
我:好的,88, 谢谢。
面试官:嗯,拜拜。
三面:(用时10分钟-hr电话)
面试官:你好我是某盟hr,之前你面试的技术已经通过了,这一轮是hr面。首先对你初步了解下。我们正常是两轮技术面,两轮hr面。
我:好的。
面试官:你目前人在哪里?
我:厦门。
面试官:那你为什么要离职呢?
我:想去大城市发展。还有现在在乙方,比较被动。
面试官:那你为什么不先考虑下深圳呢?深圳离厦门不是比较近。
我:深圳不熟,我毕业的时候就在上海,现在回来。中间balablablab…想再回去发展,可以对那边的环节无缝生活。
…中间信号不好,卡了一小会儿。
面试官:你对下一份工作有什么期望?
我:我之前了解过你们公司技术员也有23十号人,我希望和其他技术人员讨论,共同进步。
面试官:你希望的薪资是多少?
我:我希望拿到你们这个岗位薪资的顶。
面试官:具体点。
我:xxx。
面试官:因为你面试的评语,写得有点少,我去落实下。再给你回复。
我:好的。
面试官:那今天就到这里。
我:好的,88
面试官:嗯。
叮咚买菜
一面:(用时45分钟电话)
面试官:我是刚拿到你的简历,请你先做下简单的自我介绍。
我:好的,balablabalabalba…
面试官:你接触vue多久了。
我:我大概是18年开始接触的。
面试官:那也有3年了,那你讲讲vue双向绑定的原理。
我:vue2双向绑定是根据defineproperty这个函数对对象以及它的key进行setter,和getter的劫持,以及用观察者模式来实现的。大概的原理是,用递归把所有的key都definepropety一遍,并对所有的key进行订阅,然后当有key被修改了就会发通知通知所有被订阅者,并执行一遍达到双向绑定这么一个原理。
面试官:那你讲讲如何对一个对象的属性的变化进行监听。
我:心想(我刚不是说过了吗?),definepropety的第三个参数中的setter可以做到。
面试官:讲讲keep-alive的原理。
我:缓存组件,它可以缓存组件,当这个组件再次被激活的时候会调用activited钩子,keep-alive可以对路由匹配的组件进行缓存,也支持全路径缓存。它大概的一个原理是通过虚拟dom把代码片段存入documentFragment,然后存到内存中,当组件再次被激活的时候,就把这个文档片段插到对应的dom节点中。
面试官:那你讲讲路由的原理。
我:vue的路由分为两种,hash路由和history路由,首先hash路由是由路径上#后面的变量来监听路由变化的,而history是html5中的pushState来监听路由变化。
面试官:如何对网络层做优化?
我:网络层做优化有,减少网络请求,缓存一些比较不会变化的数据接口,图片请求可以做成雪碧图,把小图标做成base64图。把文件资源放到cdn。
面试官:在浏览器中输入url发生了什么?
我:首先域名输入后,会进行DNS解析到对应的ip和端口,然后现在一般的处理是nginx做路由分发,把服务器对应的资源下载到客户端,客户端拿到前端资源会按html标准进行页面渲染,其中页面会生成两个树cssom,dom,然后按顺序执行html代码,当然这个过程也遵循event loop,接着渲染head,css,body然后把js放到