记录一下我的前端面试过程吧
前言:楼主今年24岁,在上一家公司工作了接近两年,base成都。目标:10K+,面试题是我能记住且大多为没答上来的,面试完后作总结,答案为参考(欢迎指正)
1.第一场面试,一家做网络安全的公司(9-12k)
- 时间:2021年6月15日上午
- 结果:未通过
- 面试问题:
- 讲一下页面的重绘(repaint)和回流(reflow)
答案整理:
1.浏览器的渲染机制:1.首先浏览器会将HTML解析为DOM,将CSS解析为CSSOM,然后把DOM和CSSOM结合生成render tree(渲染树)
2.有了渲染树后,知道了每一个节点的样式,然后浏览器就会计算节点的位置,把节点绘制到界面上。
2.回流:当render tree的一些元素的位置或大小发生变化,导致浏览器重新渲染部分或全部文档的过程就叫做回流。
导致回流的操作:1.页面首次渲染2.浏览器窗口发生变化3.节点内容变化4.添加或删除节点。。。
3.重绘:当页面中元素样式的改变不会影响它在文档流中的位置时,浏览器会将新样式赋予给元素,这个过程就叫做重绘。
导致重绘的操作:1.background 2. visibility(可见性设置,除了display:none)---->简单记忆为:颜色、背景、边框、轮廓等改变会引起重绘
4.总结:重绘不一定引起回流,回流一定会引起重绘
5.性能方面:回流比重绘的影响大。
6.避免性能影响:
H5、CSS方面: 1.避免使用table布局 2.避免不必要的DOM层级
3.使用transform来做形变和位移,不会引起回流
Javascript方面:1. 避免使用js频繁操作DOM节点和CSS属性 2.对于大量DOM的操作,使用代码文档片段,documentFragment(这样就可以只插入一次了)如下:
HTML:<ul id="list"></ul>
const list = document.querySelector('#list');
const fruits = ['Apple', 'Orange', 'Banana', 'Melon'];
const fragment = document.createDocumentFragment();
fruits.forEach(fruit => {
const li = document.createElement('li');
li.innerHTML = fruit;
fragment.appendChild(li);
});
list.appendChild(fragment);
- CSS3动画了解多少
- 不考虑网络带宽的情况,如何使页面加载变快?(web性能优化)
面试前,忽略了这一点,这题答的很差,面试官疯狂暗示也没答上来。
答案整理:
首先,有一个老生常谈的问题:从用户输入URL到页面显示出来经历了哪些过程?
这一题换句话说就是在这些过程里面进行优化。那么,下面将进行分析:
1.用户输入URL
2.浏览器解析URL解析出主机名和端口号
3.浏览器将主机名转化为ip地址(浏览器首先会查找自身的DNS缓存列表,如果没有的话,会向默认的DNS服务器发送查询请求,然后缓存下来)
3.通过3次握手与服务器建立TCP连接
4.浏览器向服务器发送HTTP请求报文
5.服务器处理浏览器的发送的请求,并返回响应报文
6.请求响应处理完成后,通过4次挥手断开TCP连接
7.浏览器解析返回的文档,并将处理结果显示在页面上
优化方案:
1.减少HTTP请求的数量,方案:组合文件,比如合并js,css文件;优化图片,使用CSS sprite将多张ico 图片合并在一起。
2.使用内容分发网络CDN,原理:也就是在不同的地理位置部署多台服务器,用户访问到服务器的距离就更近了。
3.CSS放在顶部,JS放在底部。原理:JS加载和执行会阻塞渲染线程。假如放在head标签里,我们可以给script标签加上 defer属性.
(
PS:顺便回忆一下js资源异步加载的两种方案:defer 和 async
defer:告诉浏览器立即下载js脚本(下载过程不阻塞渲染线程),下载完成后也要等到页面解析完毕后才执行。
async:告诉浏览器立即下载js脚本(下载过程不阻塞渲染线程),等到下载完毕后立即执行,就会阻塞渲染线程了。--所以加了async的js脚本中不应该出现操作DOM的代码。
)
4.js文件动态加载,按需引入
5.减少DNS的查找,方案:使用DNS预解析,如<link rel="dns-prefetch" href="www.baidu.com">,
!慎用,用不好可能造成多次DNS查找
6.从静态资源的角度:a.压缩文件js、css,图片(一般小于8kb图片,base64处理)
b.tree-shaking删除没用到的代码
7.利用浏览器缓存
a.使用外部js文件和css文件,浏览器会进行缓存,避免了多次请求
b.通过HTTP的META设置expires和cache-control,只会缓存网页,不会缓存其中的资源和请求,如下:
<meta http-equiv="Cache-Control" content="max-age=7200"/> //7200秒
<meta http-equiv="expires" content="Mon 01 Aug 2019 00:00:00 GMT"/> //设置到期时间
8.避免出现空src或者空href,会导致发送一次请求,可能返回404
- 对网络安全了解多少(前端方向)
答案整理:我当时就只答了HTTP/HTTPS。。。应该还有很多,看到的朋友可以补充一下。
这个问题似乎问的不多。从网上截两张图吧:
简单理解:XSS:跨站脚本攻击---->通过特定方式,诱导受害者在客户端执行恶意代码。(盗用账户密码等信息)
CSRF:跨站请求伪造---->盗用受害者信息,发送伪造请求。
5. React Hooks用过吗?了解多少?然后问了UseEffect怎么卸载组件,怎么控制更新,第二个参数为空数组时会怎样?
- 暂时性死区是怎么回事?
答案整理:
在我们的js代码执行之前,浏览器会进行预解析。会做以下两件事:
1.变量名提升:只提升声明,不提升赋值
2.函数提升:整个函数提升
我们通常说var有变量提升,let、const没有,但是实际上是有的。如下代码可以验证:
let a =10;
{
console.log(a) //可以验证一下,如果没有声明提升,根据作用域链,这里应该输出10。但是却报错了
let a =5;
}
总结:let、const的初始化过程分为:声明和赋值,在声明到赋值间的距离就叫做暂时性死区。
- HTTP/HTTPS
- 自我讨伐:由于是第一次面试,很多问题没答出来。。。略显尴尬,还得加油啊
2.第二场面试,一家金融基金软件的公司(6-10k)
- 时间:2021年6月15日下午
- 结果:通过,薪资7200-7500,口头告知平均每月有2000元左右的奖金(可信度存疑)。---最终决定不去,因为工资感觉不高,而且时常有2-3月的出差,公司小,且感觉学不到什么技术
- 面试问题:
- 笔试:题目很简单,和面试官交谈,她和我说基本上能得90多分。
- 面试:谈了谈项目,都是问些基础,感觉不怎么深入。从面试官到总经理,一共面了三个人,过程除了谈技术还有画饼,很想留一下我的样子。
- 自我讨伐:面试问的问题基本都会,都让我产生了错觉,“才面第二家就拿offer了???”,所以面试回来就躺了一晚上没复习。。。懒起来了,实在不应该。
3.第三场面试,一家初创公司,做智能硬件(规模50人不到,薪资10-18K)
- 时间:2021年6月19日下午
- 结果:未知,等待通知
- 面试:只有面试,无笔试。两个面试官,一个对我上一份工作的内容很感兴趣,所以全程基本上在手机上看,应该是个技术总负责人。另一个应该是前端负责人,他负责问我问题。
- React路由的使用,如何在页面跳转的时候传参?
传参方式主要有3种:
1.Params参数
路由链接(携带参数):<Link to={`/demo/test/${id}/${name}`}>详情</Link>
注册路由(声明接收):<Route path="/demo/test/:id/:name" component={Test}/>
接收参数:let {id,name}=this.props.match.params
2.search传参
路由链接(携带参数):<Link to={`/demo/test?id=${id}&name=${name}`}>详情</Link>
注册路由 (正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数: let {search} = this.props.location.search
注:接收到的参数形式为:?id=xxx&name=xxx--->可以引入queryString进行解析
3.state参数
路由链接:<Link to={{pathName='/demo/test',state:{id:xxx,name:xxx}}}>详情</Link>
注册路由 (正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:let {id,name} = this.props.location.state
注:刷新也可以保留住参数
其他:编码方式
this.props.history.push({ pathname: "/about", state: { id:xxx } });
PS:this.props.history.push()与this.props.history.replace()区别?
- React 框架里面有过哪些优化经历?PureComponent?www.bilibili.com/video/BV1wy…
我提到了两点:
1.按需加载组件
2.PureComponent
使用普通component的2个问题:
1.只要执行setState(),即使没有改变状态数据,组件也会重新render()
2.只要当前组件render(),就会自动重新render子组件==》效率低
效率高的做法:当组件的state或props数据发生变化时才render()
原因:component中的shouldComponentUpdate()总是返回true
解决办法:
方法一:从写shouldComponentupdate()
比较新旧state或props数据,如果有变化才返回true,如果没有就返回false
方法二:使用PureComponent
PureComponent重写了shouldCompoentUpdate(),只有state或props数据有变化才返回true
注意:只是进行state和props数据的浅比较,如果只是数据对象内部数据变了,返回false。不要直接修改state数据,而是要产生新数据。
3.Hooks中的useMemo/useCallBack???
- 有用过Redux吗? 讲一下Reducer,讲一下纯函数
1.Reducer:
2.纯函数:一类特殊的函数,只要是同样的输入(实参),必定得到同样的输出(返回)。
需要准守下面这些约束:
a.不得改写参数数据
b.不会产生任何副作用,例如不能发送网络请求,不能调用输入输出设备等。
c.不能调用new Date(),Math.random()等不纯的方法。
- 对js原生熟悉吗?讲一下Promise?除了then和catch,还有什么办法能获取Promise的返回值?
- 懒加载?你在项目里面是怎么用的
我在项目里面使用lazy加载主要是用来按需加载组件。
步骤:
1.import {lazy} from react
2.const Test = lazy(()=>{import('./Test')})
3.import {Suspense} from react
4.用Suspense把我们注册的路由包裹起来,如下
<Suspense fallback={<h1>加载过程中的过度组件,我们可以自定义</h1>}> //fallback指定的组件不能通过懒加载引入,它必须是正常引入进来的。
<Route to='/Test' component={Test} />
</Suspense>
- Hook了解吗?你了解哪些?讲一下怎么在函数组件中实现生命周期钩子?在useEffect里面怎么卸载组件?
- 怎么在cra(create-react-app)中实现,css代码的模块化? moudle???
- 你在项目中客户验证是通过什么?使用什么发网络请求?axios拦截器是怎么回事?
- 用什么UI框架?了解antd吗?
- 了解VUE吗?
- 了解RN吗?
- 你是如何在cra中配置webpack的?
- 块级作用域?讲一下?
ES5中有两种作用域,全局作用域和函数作用域。ES6新增了块级作用域。
块级作用域:
1.在ES6中,用{}来界定一个块级作用域。
2.使用let、const声明的变量有块的概念,var声明的变量则没有块级作域的概念。
3.在块的内部声明let和const变量,不能够跨块访问
- setState后立马想拿到state,如何处理?
//使用setState({状态对象},callback)的第二个参数,传入一个函数,在函数里面可以拿到最新的state。如下
setState({count:1},()=>{
console.log(this.state.count)})
- 自我讨伐:可以看出,小公司更注重来个人立马就能用,问了很多很多React方面的问题。有些对于React的基础知识我由于记忆的不太深刻,导致没有答上来。接下来应该把这部分再复习一下。
4.第四场面试,一家医疗科技相关的公司(8-15k)
- 时间:2021年6月21日下午
- 结果:未知,等待通知
- 面试:只有面试,无笔试。面试官拿着我的简历看了一下,一直想问我VUE的问题,但是我对VUE一无所知。我心里想,我简历上一个VUE的字眼都没有出现,既然招VUE你干嘛叫我来...聊了一会儿后,面试官说他们也有React相关的需求。但是他好像对React一点也不熟悉...所以全程就问了我一些js,css基础
- H5里面有哪些新属性? www.cnblogs.com/vicky1018/p…
- ES6有哪些新属性?
- 你怎么理解虚拟DOM?
- 怎么理解MVVM框架?与MVC有什么区别? www.jianshu.com/p/0ae3c0d83…
1.MVVM(Model–View–Viewmodel)是一种软件架构模式。
2.简单的讲,MVVM是MVC的改进版。
先来看看MVC:
在MVC中M就是单纯的从网络获取回来的数据模型,V指的我们的视图界面,而C就是我们的ViewController。
ViewController负责View和Model之间调度。随着业务越来越复杂,视图交互越复杂,导致Controller越来越臃肿。
再来看MVVM:
所以为了解决这个问题,MVVM就闪亮登场了。他把View和Contrller都放在了View层
(相当于把Controller一部分逻辑抽离了出来),
Model层依然是服务端返回的数据模型。而ViewModel充当了一个UI适配器的角色,
也就是说View中每个UI元素都应该在ViewModel找到与之对应的属性。除此之外,
从Controller抽离出来的与UI有关的逻辑都放在了ViewModel中,这样就减轻了Controller的负担。
下面是MVVM示意图:
View层:视图展示。包含UIView以及UIViewController,View层是可以持有ViewModel的。
ViewModel层:视图适配器。暴露属性与View元素显示内容或者元素状态一一对应。一般情况下ViewModel暴露的属性建议是readOnly的,至于为什么,我们在实战中会去解释。还有一点,ViewModel层是可以持有Model的。
Model层:数据模型与持久化抽象模型。数据模型很好理解,就是从服务器拉回来的JSON数据。而持久化抽象模
型暂时放在Model层,是因为MVVM诞生之初就没有对这块进行很细致的描述。按照经验,我们通常把数据库、文
件操作封装成Model,并对外提供操作接口。(有些公司把数据存取操作单拎出来一层,称之为DataAdapter
层,所以在业内会有很多MVVM的变种,但其本质上都是MVVM)。
Binder:MVVM的灵魂。可惜在MVVM这几个英文单词中并没有它的一席之地,它的最主要作用是在View和
ViewModel之间做了双向数据绑定。如果MVVM没有Binder,那么它与MVC的差异不是很大。
- 输入一个URL到页面显示,会经历哪些过程?
- js里面怎么实现继承?
1.在ES6中:class继承的方式,使用extends关键字。在构造函数中使用super()调用父类构造函数。
2.ES5中:
a.构造函数继承
在CHILD方法中调用 PARENT.call(this),相当于给CHILD的实例设置了很多私有的属性或者方法。
特点:只能继承父类的私有属性或者方法,和其原型链没有关系。
b.原型链继承
让父类中的属性和方法在子类实例的原型上。
CHILD.prototype = new PARENT();
CHILD.prototype.constructor = CHILD;
特点:
1.继承靠的是把父类的原型放在子类实例的原型链上,想调取这些方法,是基于__proto__原型链查找机制完成的。
2.!!!子类可以重写父类上的方法(会导致父类其他实例也受影响)
c.寄生组合继承:CALL继承 + 类似于原型链继承
1.CHILD中 PARENT.call(this);
2.CHILD.prototype = Object.create(Parent.prototype);//创建一个空对象,将其的__proto__指向父类的原型
3.PARENT.prototype.constructor = CHILD;
特点:父类私有和公有的分别是子类实例的私有和公有属性方法(推荐)
- px,rem,em,vw/vh,百分比异同?
我平时没有怎么用vw/vh,这里写一下吧
vw、vh都是视口单位(Viewport units),在桌面端指的是浏览器的可视区域。移动端指的就是Viewport中的Layout Viewport(布局视口)
1.vw:1vw等于视口宽度的1%
2.vh:1vh等于视口高度的1%
3.vmin:等于vw和vh中较小的那个
4.vmax:等于vw和vh中较大的那个
rem/em
这两个都是相对长度单位。
rem:相对于根布局, 由html 元素的字体大小决定的
em:相对于自身元素的font-size,由于继承因素,font-size可以继承父元素的
-
用div模拟textArea?
方案:给div加上属性contenteditable = true;
5.第五场面试,一家教育工具类APP的公司(8-12k)
- 时间:2021年6月24日下午
- 结果:未知,等待通知
- 面试:
1.null和undefined区别
阮一峰:
null表示"没有对象",即该处不应该有值。
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。
2.简述new关键字的过程
1.创建一个空对象object,let obj = new Object()---创建对象新对象,就是指在栈内新建了一个
obj,这个obj实际上是指的堆中对应的一个地址。
2.设置原型链---这里所说原型链,就是设置新建对象obj的隐式原型即_proto_属性指向构造函数Person
的显示原型prototype对象,即obj.proto = Person.prototype
3.改变构造函数Person的this绑定到新对象obj,并且利用call()或者是apply()来执行构造函数Person
let result = Person.call(obj)
4.将第三步中初始化完成后的对象地址,保存到新对象中,同时要判断构造函数Person的返回值类型,为
什么要判断值类型呢?因为如果构造函数中返回this或者是基本数据类型(number数值,string字符串,
Boolean布尔,null,undefined)的值时,这个时候则返回新的实例对象,如果构造函数返回的值是引
用类型的,则返回的值是引用类型
6.第六场面试,一家电商公司(12-18k)
- 时间:2021年6月25日下午
- 结果:通过一面,等待二面
- 面试:
一面
1.闭包概念?怎么形成一个闭包?闭包造成的内存泄漏怎么处理?
概念:一个函数和它周围状态的引用捆绑在一起的组合。它允许一个函数可以从内部访问到它外部函数作用域。
形成:
闭包形成的3个条件:
a.函数嵌套
b.内部函数引用外部函数的局部变量
c.在两个函数外部,有变量引用内部函数
优点:可以延长外部函数局部变量的存储时间
缺点:容易造成内存的泄漏
处理内存泄漏:
在合适的地方,把我们闭包返回的函数给设置为 null。那么自然内存就被释放了。
PS:哪些行为可能造成内存泄漏?
a.意外的全局变量,比如在函数中定义变量时忘记加var。那么久相当于在window上新加了一个变量
b.setTimeout,setInterval忘记clear
c.闭包中的变量一直被引用
2.了解哪些设计模式?单例模式?工厂模式?说一下
3.如何判断两个对象完全相同?
4.说一下深拷贝? 5.说一下,react中会出现无需的render过程,你是怎么优化的。
6.说一下react生命周期?
7.说一下,怎么加快页面加载速度?(性能优化,前面有说过)
二面
时间:2021/6/29 下午
结果:通过
部门经理面试,问了下简历上的项目,30分钟左右,结束后直接叫HR面。然后回去等通知,大概下午5点告知将发offer。
7.第七场面试,一家做中间件的公司(附带自家开发商城?没大听明白)(10-15k)
- 时间:2021年6月28日上午
- 结果:应该是通过一面了,口头告知会打电话后续交流一下
- 笔试:垂直居中,盒子模型,程序执行题,两个算法题
- 面试: 1.组件间传值? 有用过context吗? 2.除了split(),你还有其他方法能拆分字符串吗? 3.箭头函数与普通函数有哪些异同?
4.ES6中map,set?
其他问题记不住了,没有问的很深入。面试官认识我上个公司的一个同事,聊了两句,就没有多问了。然后就叫他的leader过来,照着简历问了下项目。然后,就告知,他要去开会,等他有空会给我打电话进行后续的交流。
- 自我感受:面试官告知,成都这边是去年刚新成立的分部,总部在北京,然后公司规模不大,技术部门应该就几十人。成都目前10人。等着看看后续结果
8.第八场面试,一家给中石化/中石油做软件的公司(7-12K)
-
时间:2021年6月30日上午
-
结果:通过,隔天打电话给我,薪资9K,公积金比较低,双边加上一共400.
-
笔试:CSS两个题。一个算法题,还有一个程序解读题。
-
面试:一个小姐姐面试官,大概比我大3岁的样子,感觉上也不是技术大牛。
1.事件冒泡?了解吗?讲一下
2.了解哪些DOM事件?
3.问了ComponentDidMount.(她说的时候还说错了单词,我给她纠正了一下。)
4.问了一下,我简历上的项目问题。
-自我感受:由于是传统行业,我并不想去,且公司给我一种老板油腻中年人的感觉,一看就是老油条。
9.第九场面试,一家做在线教育的公司(10-18k)
- 时间:2021年6月30日下午
- 结果:未通过
- 面试:两轮面试,总体难度,个人感觉是这些面试里面最难的。
第一个面试官
1.把他的Mac给我写代码(由于我之前没用过mac,导致不知道怎么切换大小写,尴尬。。。)
第一个算法题:实现数组扁平化
//我实现了两种:1.flat() 2.toString()
第二个算法题:实现数组去重
//我实现了两种:1.利用set 2.存入一个对象中,如有重复的就不存
//面试官让我用递归再实现一次:没写完整。
2.进程有几种状态?(操作系统)
3.Webpack的HRM是怎么实现的?
没答上来。他告诉我是:首先监听我们的代码文件,若有改变,重新编译代码,然后利用WebSocket主动
将编译好的内容推送给我们浏览器。。。(大概是这样)
4.什么是Hash表?
第二个面试官
1.instanceOf 和 typeof 有什么区别?(很深入)
这个问题不是我们常规的回答。
还问了他们之间有哪些耦合的地方,就很深入。值得下来深入了解
2.假设我们在输入框中输入一个内容,请求已被发出,但它还接收到服务器的响应(假设10s,结果返回)。我们在这个时间里,立马再发出第二次的请求,它的结果立马就返回了,并显示在我们的内容里面。但是10后,第一次发出的请求,结果返回了,然后覆盖了第二次请求的结果。请提出方案来解决这个问题?
听到这个问题----懵逼树上懵逼果,懵逼树下你和我...
然后我想了一下20秒:
可以用防抖,在第一次请求发出后,设置一个setTimeOut(),如果在时间段内,在发请求,就cancel()掉。
然后面试官说,可以,但这个方案有问题,无法正确设置间隔时间。然后疯狂暗示我继续想,但我也想不起来了。
他看我想不起来就:说可以给每一个请求设置一个编号,比如1,2,3...然后每次发请求就带给服务器。
服务器返回的时候回传给客户端。然后进行比较,如果1<2,就不要1. 然后他说这种方案还有问题,让我再想。。。我继续懵逼,然后他说了第三种方案,我没心思听了,也就没记住
3.这次,给了我一个thinkpad,让我手写的深拷贝?
由于我之前看过,不到3分钟就给写出来了。
面试结束:他去找第一个面试官合计,估计就不要我了,233...
-自我讨伐:没有解决实际问题的方案,平时缺乏的很
10.第十场面试,一家做医疗药品网站后台的公司(8-15K)
- 时间:2021年6月31上午
- 结果:通过
- 面试:
1.PureComponent? 什么是浅比较?
2.webpack打包流程是怎么样的?
3.闭包?闭包可以解决那些问题?
-自我感受:第二天告诉我面试通过,11K底薪加上季度项目奖。我拒绝了,因为公司开发人员只有10来个,也是一个传统行业。
11.第十一场面试,一家做家装APP的公司。(15-25k)
- 时间:2021年7月1日下午
- 结果:通过一面(很多问题没答上,面试官也给了我二面机会???)
- 电话面试:真的讨厌电话面试,听不清楚问题,有几个问题,我重复让面试官说了两次,我都不好意思了(像耳朵有问题一样)。
1.归并算法?
2.快速排序?
-自我感受:难度较大,我以为过不了一面,隔天打电话过来告诉我一面过了,准备现场二面。但是我不打算去了,已经接offer。
结果:
拿到了第6场面试的offer,具体薪资就不说了,上面有个范围,也达到了我的期望。7月6日上班
面试总结与感受
最近太累了,后面补上。2021/7/3 晚23:35