面试造火箭,工作拧螺丝!
在IT技术圈里,只有百分之十的人能够进入大厂,剩下的百分之九十的小伙伴只能在普通的公司,厌烦一些标题党,动不动就能进入BAT等大厂。抛开那些夺人眼球的词语,回归到面试本质,关注面试本身,总结最近3年里长文的web前端开发工程师面试题(不涉及具体很细节的知识点,适合初中级前端开发工程师)。
1、HTML(5)和CSS3方面1、前端与后端数据交互的格式有哪些,为什么大部分现在都用json而不用xml?
XML:<person><name>蛋糕哥</name><age>3岁</age></person>
JSON:{ “name”:”蛋糕哥”,”age”:3}
从上可以看出,JSON书写更方便节省字节、更轻量,前后都有直接解析JSON的方法(JSON.stringfity/parse)使用方便。
2. 说一下CSS盒模型
CSS的盒模型包含了以下几个内容:
margin,padding,border,content
在计算盒子宽高的时候,IE和Chrome会有一些区别。IE算到border,Chrome的宽度只包含content区域,因此CSS3提供了box-sizing这个属性来修改。
3. 请用5种方式实现元素垂直居中
1)flex
.wrap{
height:100%;
position:relative;
display:flex;
justify-content:center;
align-items:center;
}
2)Tranform
.static{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
3)定位 margin负值
.static{
position:absolute;
left:50%;
top:50%;
margin-top:-100px;
margin-left:-100px;
}
4)定位 margin:auto
.static{
position:absolute;
left:0;
right:0;
bottom:0;
top:0;
margin:auto;
}
5)JS动态计算top、left值
4、什么是BFC?垂直margin重叠是为什么?怎么解决这个问题?
答:BFC又称块级格式上下文,通俗来说是一个独立的布局环境,也可以理解为是一个箱子,箱子内部的元素无论发生怎样的变化都不会对外部造成影响。并且,在一个BFC中,块元素与行元素都会垂直地沿着其父元素的边框进行排列。
如何触发BFC:
a. 浮动元素,float除none以外的值;
b. position的值不为static或者relative;
c. display不为none;
d. overflow除了visible以外的值。
BFC的应用:
a. 解决浮动塌陷问题;
b. 自适应两栏布局(运用BFC可以阻止元素被浮动元素覆盖的特性来实现自适应两栏布局,方法:给没有浮动的元素加overflow:hidden)
c. 解决设置margin值重叠问题。
5. 简单描述http或https协议,以及为什么要三次握手?什么是长链接
答:http/https是超文本传输协议,基础TCP请求与相应的模式,是目前主流的web传输协议,一般包含请求头,请求体和响应头等。
https相较于http更安全,增加了证书ssl加密,端口是433。
三次握手也就是三次网络连接,客户端携带SYN=1,SEQ = x信息给服务端,服务端接收到后,就知道有一个客户端想要连接,然后服务端就会开启一个TCP socket的端口,然后返回数据给前端也是SYN=1,SEQ=Y,ACK = x 1,客户端接收到后,再发送一个seq和ACK 1(防止开启无用的链接或者网络延迟丢包),服务器无法确定到底客户端有没有收到消息。
6. 什么是reflow与repain?哪些操作会触发reflow,如何避免
reflow:回流。当元素的尺寸,DOM结构发生变化时,浏览器会重新渲染页面,称为回流。
repain:重绘。当元素的样式发生变化(结构不发生变化)时,以下常见的操作都会触发:
浏览器窗口大小改变;
元素尺寸、位置、内容发生改变;
元素字体大小变化;
添加或者删除可见的dom元素;
激活CSS伪类(例如:hover)等;
通过class的方式集中改样式,documentFragment缓存节点,避免使用table、calc,做动画的节点脱离文档流(新创建图层)。
总结:减少DOM操作!
7.什么是浏览器缓存(强缓存和协商缓存)?
当浏览器访问咨询后,会被浏览器缓存到本地,当下次访问页面时,如果没有过期,会直接读取缓存,加快浏览器的加载效率。
http缓存机制:
1)Expires:通过设置最大缓存时间,当时间超过了就去服务器下载;
2)http1.1,cache-control:max-age=time,当time过期后,检测etag带上etag往服务器发请求,如果etag没变,直接告诉浏览器读本地缓存,如果没有etag就会检测Last-Modified,判断如果上一次更改的时候,距离本次访问时间比较久,说明文件没有发生改变,返回304。
强缓存就是当前访问时间还在设置的最大时间范围内。
协商缓存就是时间过了,通过检查etag或者last-modifed来使用缓存的机制。
8. 说一下浏览器垃圾回收机制
老:标记清除算法,GC会检测当前对象有没有被变量所引用,如果没有就回收。
新:Scavenge,把内存空间分为两部分,分别为From空间和To空间。当一个空间满了以后,会把空间中活动对象转移到另外一个空间,这样互换。
9.什么是事件委托
事件委托本质上是利用浏览器事件冒泡机制,因为事件在冒泡过程中会上传到父节点,并且父节点可以通过事件对象获取到目标节点。因此,可以把子节点的监听函数定义在父节点上。由于父节点的监听函数统一处理过个子元素的事件,这种方式成为事件代理。采用事件代理,我们可以不必要为每个子元素都绑定一个监听事件,这样减少了内存上的消耗,也是常见的JS性能优化点。
10.什么是响应式布局?如何实现
书写一套CSS样式,适用于PC和移动端能够正常浏览显示。
注意:响应式不能使用固定单位,需使用max-width、min-width等能自动缩放的单位。
2、JS方面(ES6/ES7)1. 在JS中什么是面向对象程序设计,面向对象设计优点?
在JS中面向对象更多说的是通过构造函数或者class封装一个独立的功能,以达到代码的复用。
面向对象的三个特点:
封装:通过对象把属性和方法封装起来,相似对象的话采用构造函数或者类new得到。
继承:通过混合继承(构造函数和原型)的方式,可以达到属性和方法的复用。
多态:通过对象属性覆盖,可以让继承的对象拥有更多行为。
面向对象的程序设计是组织代码的方式,能提升开发效率和代码的可维护性。
2. 什么是作用域以及作用域链?
作用域是指程序源代码中定义变量的区域,限定一个变量可访问范围的,作用域的本质是对象。JS采用的词法作用域,在书写代码的时候就已经确定好了。
在ES6环境下,包含3个作用域:全局globel、函数作用域、快级作用域( {} )(eval)
作用域链:当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,则会从父级执行上下文的变量对象中查找,直到找到全局上下文的变量对象(全局对象)。
这种由多个执行上下文的变量对象构成的链表就叫做作用域链,目的是保证对执行环境有权访问的所有变量和函数进行有序访问;本质是为执行上下文的scope属性,存储所有的变量,包括局部和全局控制变量的使用顺序。
3. 什么是闭包,闭包的好处和坏处分别是?
当函数可以记住并访问外部作用域时,我不作用域就称为闭包。
形成的原因:外层函数的作用域对象无法释放。
作用:为了封装对象的私有属性和方法,避免全局变量的污染。
缺点:使用不当会造成内存泄露。
4.什么是Ajax,如何封装一个Ajax?Get请求与Post请求的区别?
Ajax全称是异步js与xml技术,通过它与后台服务器进行数据交换,可以使网页实现异步更新。换言之,在不同重新加载整个页面的情况下的,对网页进行局部更新。
1)nex xmlhttprequset对象
2)open(method,url,true)
3)绑定redaystatechange事件
4)调用send方法,如果是post请求,可以传递参数
前端的请求方式除了常用Get和Post,还有update,delete,put等(restful api设计)
三分方面来说:能不能缓存,传参数方式,传参大小
GET请求可被缓存,保留在浏览器历史记录中 ,请求的参数是直接跟在URL上,因此不应传递敏感数据。
GET请求有长度限制(2048字符),IE和Safari浏览器限制2k;Opera限制4k;Firefox,Chrome限制8k 。
GET请求通常只应当用于从后台获取数据。
POST请求不会被缓存,不会保留在浏览器历史记录中
POST请求对数据长度没有要求。
POST请求通常用于往后台提交数据。
5.说一些ES6、ES7新特性
let/const定义变量(块级作用域);结构,从对象和数组中提取值;箭头函数;字符串模版;扩展运算符...;对象的简写;module;promise(async);class;对原生对象的扩展(新增加了很多方法) ;for-of (Object.keys,values,entries等);Symbal();
不常用的proxy,reflect,generate函数,map和set
6. 什么是跨域,解决跨域问题常用的方式有哪些?
跨域是浏览器端行为,根据同源策略,当请求的协议、域名、端口只有一个不同,就会跨域,跨域是浏览器为了安全存在的机制,浏览器会把跨域请求的数据去掉,同时报错。
在实际开发难免会出现跨域的情况,解决方案通常有
1)JSONP技术,利用了script的src属性没有跨域限制,img的src也没有跨域限制
2)CORS,当在相应头信息中添加access-control-allow-origain属性,浏览器读取到就会允许返回数据。后台配置,或者下一个浏览器插件即可。
3)后台代理(Node)
4)Iframe域的提升(很少)
7. 前端安全你有了解吗?什么是XSS攻击和CSRF 跨站请求伪造?怎么预防?
在工作中会注意以下前端安排问题:
1)XSS跨站脚本漏洞攻击,通常不信任用户的输入,转义输入输出内容(encodeURIComponent),括号、尖括号等。利用用户对站点的信任。
2)CSRF跨站请求伪造
一种挟制用户在当前已登录的web应用中执行非本意的攻击,简而言之就是利用用户登录发起恶意请求。
预防:
1)添加验证码不让第三方访问cookie对cookie设置samesite,请求验证加token(用户体验稍差)。
2)密码问题:对密码进行加密(MD5等)。
8. JS加载会阻塞页面渲染吗?会的话该怎么解决呢?CSS呢
会。
因为JS可以操作DOM,浏览器为了防止渲染过程中出现不可预期的结果,让GUI渲染线程和JS引擎线程互斥,即解析器在遇到<script>标记时,会立即解析并执行脚本。
defer:并行下载,在页面解析完后执行,会按照script的顺序执行,代码有依赖顺序依赖的时候选用。
async:异步下载代码,下载完后立即执行,不会按照页面的script顺序。CSS的加载不会阻止DOM解析,页面的绘制会等待CSS解析完成才执行。
3、框架方面1.什么是vdom(虚拟DOM)?为何要使用vdom?简单地描述一下什么是diff算法?
浏览器最费操作的就是DOM操作,结构复杂,属性太多,节点与节点之间还相互关联。Vdom是一类技术栈,使用JS对象来模拟DOM结构,将ODM变化的对比放到JS层来做,提高效率。
Diff算法是对比新旧两个虚拟DOM节点,只修改变化的地方,其他节点不动。大概实现思路为遍历新节点:与旧节点同级比较,如果节点相同,再比较属性值,再递归比较子节点,直到全部比较完,再进行下一次同级比较。当遇到不相同的地方记录下来,下一次事件循环的时候统一更新节点。
2. 简单说一下对MVC、MVVM的理解?
1)M:model数据源,一个列表的数据、表单数据等;V:view视图,HTML CSS;C:controllor控制器,控制视图或者数据的变化。
2)MVVM,在MVC模式上算是一个微创新,M和V和上面一样的,VM:viewmodel,相对于M/V之间的一个桥,view通过事件绑定影响到model,model可以通过数据监听来影响视图,这样就让View和Model分离了更加利于视图的复用。
3. 简单说一下对Vue模板的理解
模版、字符串、有逻辑、可以嵌入JS变量。模版会被编译成render函数,执行render后返回的是vdom(vnode)。
Vue的vdom是借鉴了snabbdom,在updateComponent中实现vdom的patch,首次渲染是会执行updateCompoent,在data每次修改的时候,执行updateComponent。
4.Vue2.x如何实现数据的双向绑定的?
Vue通过数据劫持(Object.DefineProperty()) 订阅发布模式
监听器 Observer:用来劫持并通过Object.defineProperty监听所有属性(转变成setter/getter形式),如果属性发生变化,就通知订阅者。
订阅器 Dep:用来收集订阅者,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
订阅者 Watcher:监听器Observer和解析器Compile之间通信的桥梁;如果收到属性的变化通知,就会执行相应的方法,从而更新视图。
解析器Compile:可以解析每个节点的相关指令,对模板数据和订阅器进行初始化。
主要做的事情:
1)在自身实例化时往属性订阅器(dep)里面添加自己。
2)自身有一个update()方法。
3)待属性变动dep.notice()通知时,能调用自身的update()方法,并触发解析器(Compile)中绑定的回调。
总结:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
5. Vue,React子父组件如何通讯?
由于单项数据流的规范,Vue和react都遵循通讯机制。
vue和react都是使用prop传递数据给子组件,vue需要提前在子组件中提前使用props声明,react不用。
React中子组件传递数据到父组件(状态提升),同样是通过父组件给子组件传递属性,区别是属性值为一个函数函数引用(需要绑定函数的this),然后在子组件中调用这个函数即可,传递相应的参数。
Vue中子到父,是通过在使用子组件的时候绑定自定义事件,在子组件内部拿到事件名称,再通过this.$emit(‘事件名’)触发并传递参数。
其他方式:全局$bus,provide/inject,$refs/$parent/$children ,$attrs/$listeners ,仓库,storage,url,1.x还有brodercast/dispatch 广播/派发已过时。
6.简述Vue和React的框架的特点以及区别
Vue(MVVM)和react都是组件化、数据驱动型的框架,现在基本都差不多了。
区别:
体积:vue独立一个 30K ,react 160K
学习成本:vue是面向模版编程易学,react函数式编程,需要提前学习ES6 。
效率:vue初始化渲染是比较慢的,是因为vue要把所有的属性都使用object.defineproperty劫持,react就不需要。但是在运行时,vue要快一点,只有数据发生变化就会执行set,再通知指令去更新视图,而react需要执行setState函数,进行diff的比较。
7.Vue-router路由传参的方式有哪些?
1)js导航的xx.push({path:”/user”,query:{ }})
2)动态路由 {path:”/user/:id” name:”user”}
3)meta
4)Storage/仓库
8.不用vue-cli如何搭建一个vue项目?
答:需要使用构建工具webpack(当然还有其他工具gulp,browserify),通过entry配置入口文件;output配置打包输出;module配置loader(loader是用来处理文件的),一般配置处理less/sass,二进制图片或字体等,babel-loader处理ES6/7等,还需要配置vue-loader处理.vue文件;通过plugins配置插件;还需要通过devServer(端口,代理,historyApiFallback,刷新浏览器等)配置开发服务器,配合使用webpack-dev-server。还有一些杂项可以通过resolve来配置(别名,去掉扩展名等)。
9.Vue3有了解过吗?谈谈你对Vue3的理解
大概地学的一下,我觉得这次升级的主要的composition API为了解决代码复用问题,从3个方面来理解:
1)性能。使用proxy代理替换掉了defineProperty劫持,由于defineProperty的局限性无法检查对象属性的改变,同时默认递归data里面的数据做响应式。Proxy是懒递归,当我们操作数据是对象的时候才会去递归代理。
2)复用。原来的optionsAPI,同一个业务逻辑分散在不同的配置项中,跨组件复用起来很麻烦(2.x采用mixins),现在可以封装在函数里面,哪里需要了,就直接导入。
3)对TS的支持。复用的功能多半是函数,再定义接口和类型就很方便了。
目前的缺陷就是兼容性差一些,IE11都不支持。
10.谈谈你是如何实现前端权限验证的?
我知道的前端的权限验证有两个:
1)路由权限:不同的权限对应着不同的路由页面,同时侧边栏也需要根据不同的权限来异步生成。
2)按钮权限:(使用一个指令,传递权限标识,然后和当前用户的权限比较,如果不匹配就隐藏节点) 比如有些按钮可能只有主管才能使用。
路由权限流程:
登录:当用户填写完账号和密码后向服务端验证是否正确,验证通过之后,服务端会返回一个token,拿到token之后(我会将这个token存贮到cookie中,保证刷新页面后能记住用户登录状态),前端会根据token再去拉取一个 userinfo 的接口来获取用户的详细信息(如用户权限,用户名等信息)。
权限验证:通过token获取用户对应的 role,动态根据用户的 role 算出其对应有权限的路由,通过 router.addRoutes 动态挂载这些路由。
4、工具方面1.使用过哪些前端工具?
了解过gulp,但是好像现在已经过时了。目前在开发工程中都使用webpack。
2.有了解过webpack吗?常用的配置项有哪些?
webpack称为模块打包机。它将资源都看成是一个模块,并且把页面逻辑当作一个整体,通过一个给定的入口文件,webpack从这个文件开始,找到所有的依赖文件,将各个依赖文件模块通过loader和plugins处理后,然后打包在一起,最后输出一个浏览器可识别的JS文件。
常见的配置包括:
mode:配置webpack环境,包含development和production环境 (4 )
entry:配置项目的入口文件
output:打包后的文件名,存放的地址,chunk的名字。。。
module:loader test use指定loader
plugins:插件
devserver:配置webpack-dev-server
resolve:杂项,别名,文件的扩展名。。。
devtools:soure-map
3.webpack常用的插件有哪些?分别的作用什么?
MiniCssExtractPlugin :抽离css从js中
DefinePlugin:定义全局变量
htmlWebpackPlugin 设置模版 会自动帮我们打包好的文件路径注入模版
PurifyCSSPlugin:去掉没用的css样式
CopyWebpackPlugin:拷贝静态资源
HotModuleReplacementPlugin:组件热更新
4.git与svn的区别在哪里?
答:git 和svn最大的区别在于git是分布式的,而svn是集中式的。因此我们不能在离线的情况下使用svn。如果服务器出现问题,我们就没有办法使用svn来提交我们的代码。
5、常规算法方面1、JS中数据结构与算法
数组,对象集合,set,Map
栈LIFO、队列、链表、字典、树
2、排序(冒泡,选择,插入,快排)
选择排序,选假设一个最大,与剩下的比较,如果比max大就交换
function select_sort(A){
for(let i = 0;i<A.length;i ){
let max = A[i];//假设第一个最大
for(let j = i 1;j < A.length;j ){
if (max < A[j]) {
max = A[j];
let mid = A[j];
A[j] = A[i]
A[i] = mid;
} }}}
插入,准备一个新数组,然后依次去原数组中取值,先取一个放到数组里,再取第二个跟新数组里面的进行比较,如果大于就放到后面,小于就再往前找一个,直到找到比当前要小的数,并把它插入后面。
function insert(data,i,t){ //假设data为有序数组,插入
//data有序数组,i数组最大的索引,t要插入的节点
let p = i-1;//p为下一个要比较的元素的索引值
while(p>=0 && data[p] > t){ //data[p] > t 当比较的元素比传进来的元素大
data[p 1] = data[p]; //错位,把当前元素赋值给下一个元素
p-- //p往前走
}
data[p 1] = t //写入空位
}
function insert_sort(data){
for (var i = 0; i < data.length; i ) {
insert(data,i,data[i])
}}
快排,利用递归
function querySort(arr){
if (!Array.isArray(arr)) return
if(arr.length <= 1){
return arr
}
var mid = arr.splice(Math.floor(arr.length/2),1)[0]
var left = [], right = [];
for(let i=0,len = arr.length;i<len;i ){
if (arr[i] >= mid){
right.push(arr[i])
}else{
left.push(arr[i])
}
}
return querySort(left).concat([mid],querySort(right))
}
3.数组的flat拉平
function flat(arr){
var arr1 = [];//闭包缓存
function _flat(arr){ //[2,3]
for (var i = arr.length - 1; i >= 0; i--) {
if (Array.isArray(arr[i])) {
_flat(arr[i])
}else{
arr1.push(arr[i])
} }}
_flat(arr)
return arr1
}
function flat(arr) {
arr.toString().split(',')
return arr
}
4、实现一个方法,找出一个数组中重复的元素
一:Array.prototype.repeNum = function(){
let new_arr = this.sort(); //先排序
let res = [] ;
for( let i = 0 ; i < new_arr.length ; i ){
if(new_arr[i] == new_arr[i 1] && //判断是否重复,是否已经放入容器
new_arr[i] !=new_arr[i-1]){
res.push(new_arr[i]);
}}
return res
}
二:Array.prototype.repeNum = function(){//不排序,利用对象的key
function arrMore(arr){
if (!arr.length) return
let obj = {};
for (var i = 0,len=arr.length; i < len; i ) {
var val = obj[arr[i]];
if(!val){
obj[arr[i]] = 1
}else{
obj[arr[i]] = 1
} }
var arr = [];
for (let [key, value] of Object.entries(obj)) {
if(value>1){
arr.push(key-0)
}}
return arr
}}
三:Array.prototype.repeNum = function(){
if (!arr.length) return
var ret = arr.filter((val, index) => arr.indexOf(val) != index);//先找到有重复的
return [...new Set(ret)];
6、其他问题6.1、技术方面1、最近做什么项目?在项目遇到什么问题?如何解决的呢?
结合自己的实际情况进行回答,面试前可以好好准备一下。如果是应届生,把自己平时学习的知识和练习的项目总结好。
2、最近在学什么技术?
该问题的目的可能是想考查你平时是否爱学习,对新技术有没有一定的敏感度。不一定要了解多深刻,了解核心内容即可,但不建议说没有。
3、平时喜欢逛什么社区或者技术论坛?
主要是想了解你平时都是通过哪些途径学习,前端开发比如像掘金,阮一峰老师博客,github等。
4、你对加班怎么看?
根据自己的实际情况进行回答。需要提醒的是,互联网企业,IT技术岗位,不加班是几乎不可能的。
5、你还有什么想了解的吗?
技术面的时候不建议问薪资福利,技术面如果没问题,这些后期hr会进行沟通。可以问团队正在做的项目类型等技术方面的问题。
6.2、HR方面你会发现,有的小伙伴技术能力并不差,一面、二面技术面试都没问题,但hr面试后便没有下文。对于HR面试环节,很多小伙伴不是很重视,尤其是刚毕业的小伙伴,殊不知HR也有决定权。所以,在HR面试环节也需要稍微准备一下。
1、为什么要换工作?
换工作无非于那三个原因,钱给得不够、干得不开心、公司没有上升空间。只要大家的原因积极正向一点,别说前公司的坏话就好了,其它自由发挥。
谨记:哪怕公司再内卷,也千万不能说公司坏话。
2、对薪水有什么期望?
可以根据当前岗位给定的范围,比如10K-15K,可以要个13K,不要超过,也不要低于最小值。
3、对未来有什么规划?
回答不要太空泛,可以从近期规划和长远规划两个方面出发进行讲解。
如:近期规划:深入地学习前端面向对象OOP,函数式编程等;长远规划:未来3-5年都在前端技术方向等。
4、你还有什么想了解的吗?
现在可以充分了解公司的福利、待遇、公司环境等。面试到这里也不必羞涩了,有什么想了解的尽管问。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved