2021年web前端基础面试题
全方面面试总结
1.javascript
JS面试题
JS面试题
手写无敌JS
原始类型(基础类型)
boolean
null
undefined
number
string
symbol
null不是对象类型,虽然 typeof null
会输出 object
,但是这只是 JS 存在的一个悠久 Bug.
对象(Object)类型
对象类型和原始类型不同的是,原始类型存储的是值,对象类型存储的是地址(指针)。
typeof
vs instanceof
涉及面试题:typeof
是否能正确判断类型?instanceof
能正确判断对象的原理是什么?
typeof
对于原始类型来说,除了 null
都可以显示正确的类型
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof
对于对象来说,除了函数都会显示 object
,所以说 typeof
并不能准确判断变量到底是什么类型
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
如果想判断一个对象的正确类型,这时候可以考虑使用 instanceof
,因为内部机制是通过原型链来判断的,
const Person = function() {}
const p1 = new Person()
p1 instanceof Person // truevar str = 'hello world'
str instanceof String // falsevar str1 = new String('hello world')
str1 instanceof String // true
类型转换
==vs===
首先会判断两者类型是否相同。相同的话就是比大小了
类型不相同的话,那么就会进行类型转换
会先判断是否在对比
null
和undefined
,是的话就会返回true
判断两者类型是否为string和number,是的话就会将字符串转换为number
判断其中一方是否为boolean,是的话就会把boolean转为number
判断其中一方是否为
object
且另一方为string
、number
或者symbol
,是的话就会把object
转为原始类型再进行判断
[] == ![]
①、根据运算符优先级 ,! 的优先级是大于 == 的,所以先会执行 ![]
!可将变量转换成boolean类型,null、undefined、NaN以及空字符串('')取反都为true,其余都为false。
所以 ! [] 运算后的结果就是 false
也就是 [] == ! [] 相当于 [] == false
②、根据上面提到的规则(如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1),则需要把 false 转成 0
也就是 [] == ! [] 相当于 [] == false 相当于 [] == 0
③、根据上面提到的规则(如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较,如果对象没有valueOf()方法,则调用 toString())
而对于空数组,[].toString() -> '' (返回的是空字符串)
也就是 [] == 0 相当于 '' == 0
④、根据上面提到的规则(如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值)
Number('') -> 返回的是 0
相当于 0 == 0 自然就返回 true了
总结一下:
[] == ! [] -> [] == false -> [] == 0 -> '' == 0 -> 0 == 0 -> true
那么对于 {} == !{} 也是同理的
关键在于 {}.toString() -> NaN(返回的是NaN)
根据上面的规则(如果有一个操作数是NaN,则相等操作符返回 false)
总结一下:
{} == ! {} -> {} == false -> {} == 0 -> NaN == 0 -> false
执行上下文(EC)
https://www.cnblogs.com/echolun/p/11438363.html
闭包
闭包的定义其实很简单:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。
在 JS 中,闭包存在的意义就是让我们可以间接访问函数内部的变量.
一篇文章看懂JS闭包,都要2020年了,你怎么能还不懂闭包?
闭包的应用场景
this
call、apply与bind有什么区别?
1.call、apply与bind都用于改变this绑定,但call、apply在改变this指向的同时还会执行函数,而bind在改变this后是返回一个全新的boundFcuntion绑定函数,这也是为什么上方例子中bind后还加了一对括号 ()的原因。
2.bind属于硬绑定,返回的 boundFunction 的 this 指向无法再次通过bind、apply或 call 修改;call与apply的绑定只适用当前调用,调用完就没了,下次要用还得再次绑。
3.call与apply功能完全相同,唯一不同的是call方法传递函数调用形参是以散列形式,而apply方法的形参是一个数组。在传参的情况下,call的性能要高于apply,因为apply在执行时还要多一步解析数组。
能说说深浅拷贝的区别与实现吗?
常用八种继承方案
JS 20道概念虽老但也略有收获的JS基础题,快速做题,高效复习,不妨试试?
防抖与节流
防抖与节流函数是一种最常用的 高频触发优化方式,能对性能有较大的帮助。
- 防抖 (debounce): 将多次高频操作优化为只在最后一次执行,通常使用的场景是:用户输入,只需再输入完成后做一次输入校验即可。
function debounce(fn, wait, immediate) {let timer = nullreturn function() {let args = argumentslet context = thisif (immediate && !timer) {fn.apply(context, args)}if (timer) clearTimeout(timer)timer = setTimeout(() => {fn.apply(context, args)}, wait)}
}
复制代码
- 节流(throttle): 每隔一段时间后执行一次,也就是降低频率,将高频操作优化成低频操作,通常使用场景: 滚动条事件 或者 resize 事件,通常每隔 100~500 ms执行一次即可。
function throttle(fn, wait, immediate) {let timer = nulllet callNow = immediatereturn function() {let context = this,args = argumentsif (callNow) {fn.apply(context, args)callNow = false}if (!timer) {timer = setTimeout(() => {fn.apply(context, args)timer = null}, wait)}}
}
手写 call、apply 及 bind 函数
手写new
在调用 new
的过程中会发生以上四件事情:
- 新生成了一个对象
- 链接到原型
- 绑定 this
- 返回新对象
根据以上几个过程,我们也可以试着来自己实现一个 new
function create() {let obj = {}let Con = [].shift.call(arguments)obj.__proto__ = Con.prototypelet result = Con.apply(obj, arguments)return result instanceof Object ? result : obj
}
以下是对实现的分析:
- 创建一个空对象
- 获取构造函数
- 设置空对象的原型
- 绑定
this
并执行构造函数 - 确保返回值为对象
对于对象来说,其实都是通过 new
产生的,无论是 function Foo()
还是 let a = { b : 1 }
。
对于创建一个对象来说,更推荐使用字面量的方式创建对象(无论性能上还是可读性)。因为你使用 new Object()
的方式创建对象需要通过作用域链一层层找到 Object
,但是你使用字面量的方式就没这个问题。
function Foo() {}
// function 就是个语法糖
// 内部等同于 new Function()
let a = { b: 1 }
// 这个字面量内部也是使用了 new Object()
更多关于 new
的内容可以阅读我写的文章 聊聊 new 操作符。
instanceof 的原理
涉及面试题:instanceof 的原理是什么?
instanceof
可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype
。
我们也可以试着实现一下 instanceof
function myInstanceof(left, right) {let prototype = right.prototypeleft = left.__proto__while (true) {if (left === null || left === undefined)return falseif (prototype === left)return trueleft = left.__proto__}
}
以下是对实现的分析:
- 首先获取类型的原型
- 然后获得对象的原型
- 然后一直循环判断对象的原型是否等于类型的原型,直到对象原型为
null
,因为原型链最终为null
为什么 0.1 + 0.2 != 0.3
localStorage和sessionStorage
常用的数组API
sort
小于0=>false,不换位置 , 大于0=>true,换位置
如果[2,3] , 如果是a-b =>2-3<0 不换位置,那不就是升序了, 如果是b-a =>3-2>0 那就换位置[3,2]不就是降序了.
结合实际,很好理解
对象API
能说下你理解的作用域和作用域链吗
介绍下原型和原型链?
https://www.cnblogs.com/echolun/p/12321869.html
https://www.cnblogs.com/echolun/p/12384935.html
Fetch
首先我们要知道javascript中的万物皆对象,那么万物也就包括那些基础数据类型:string,number,Boolean等,当然除了null和undefined外,虽然是typeof null 为object ,但是这只是JS的一个小BUG,实际上null并未为对象,这些对象在JS中称之为包装对象,除了包装对象以外就是普通对象了。当然这些对象都是构造函数来创建的,构造函数虽然叫做构造函数但是与普通函数没什么区别,通过构造函数new出来的叫做实例,这个实例的__proto__
就指向他的构造函数的prototype,所以说每一个函数都会有一个prototype,这个prototype就叫做原型,那么原型其实也是一个对象,那么说直接点,原型对象就是一个包含很多属性和方法的对象,既然原型是对象,那么原型的__proto__
也就是指向object.prototype。当然这些普通的构造函数都是来源于Function这个构造函数,Function这个构造函数很特殊,既然Function是一个函数,所以他就是自己创建自己,所以他的__proto__
和prototype都是指向Function.prototype,所以Function.prototype的constructor就指向Function本身,但是当我console.log(typeof Function.prototype)
时他居然输出的是function,但是Function.prototype的__proto__
又是指向Object.prototype
这就令人费解了,在我查阅相关文档的时候,文档明确指出,这奇葩的操作是为了兼容旧版的ECMAscript.
当一个对象访问某个属性时,它会先查找自己有没有,如果没有就顺着__proto__
往上查找创建自己构造函数的原型有没有,这个查找的过程就.是原型链,原型链的顶端是null。
去重数组
数组排序
map和forEach的区别?
相同点:
都是循环遍历数组中的每一项,forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是
item(当前每一项)、index(索引值)、arr(原数组),需要用哪个的时候就写哪个,匿名函数
中的this都是指向window,只能遍历数组。
复制代码
不同:
map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值。(原数组进行处理之后
对应的一个新的数组),map()方法不会改变原始数组map()方法不会对空数组进行检测forEach()
方法用于调用数组的每个元素,将元素传给回调函数.(没有return,返回值是undefined,forEach
对于空数组是不会调用回调函数的。)
EventLoop
什么是Symbol,他是使用场景是什么
事件委托的应用场景
JS面试题
var a = 1,b =2;
console.log(a+++b)var result = (function(){return 1;
},function(){return "2"
})()
console.log(typeof result)
var a={num:1,toString:function(){return a.num++;}}if(a==1&&a==2&&a==3){console.log("恭喜答对啦!");}else{console.log("还是错了小子!");}
2.css
nth-of-child和nth-of-type的区别
css选择器+和 ~
css3选择器
CSS 常考面试题资料
position的属性值有哪些,它们的区别是什么
列举一下移动端适配方案
less和CSS的区别,less的函数了解过什么
BFC
居中布局
- 水平居中
- 行内元素:
text-align: center
- 块级元素:
margin: 0 auto
absolute + transform
flex + justify-content: center
- 行内元素:
- 垂直居中
line-height: height
absolute + transform
flex + align-items: center
table
- 水平垂直居中
absolute + transform
flex + justify-content + align-items
去除浮动影响,防止父级高度塌陷
- 通过增加尾元素清除浮动
:after / <br> : clear: both
- 创建父级 BFC
- 父级设置高度
一篇文章弄懂flex布局
请简述下CSS选择器的权重与优先规则。
这个没啥好说的,!important > 行内样式 > ID选择器 > 类选择器 > 元素选择器 > 通配符选择器 > 继承 > 浏览器默认属性。
用css实现一个三角形
BEM
3.浏览器与HTTP相关知识
网络方面还可以吧(我默默的点点头),说说TCP的长连接和短连接的区别?
如果了解得比较深入,可以说说各自的优缺点。
一、短连接
概念:客户端与服务器建立连接开始通信,一次/指定次数通信结束之后就断开本次TCP连接,当下次再次通信时,再次建立TCP的链接。优点:不长期占用服务器的内存,那么服务器能处理的连接数量是比较多的缺点:1、因为要等到发送或者获取资源时,才去请求建立连接,而且http协议只能客户端主动向服务端发送数据后,服务端才返回对应的数据,那么服务端想主动发送数据给客户端呢?Websocket可以让服务端主动发送数据给客户端,或者要等到下一次要请求数据时,才发送,比如我们采用轮询(30秒或者更长)拉取消息, 那么服务器与客户端通信的实时性就丧失了。2、客户端采用轮询来实时获取信息,或者说大量的客户端使用短连接的方式通信,那么就浪费了大量的CPU和带宽资源用于建立连接和释放连接,存在资源浪费,甚至是无法建立连接。比如经典的http长轮询(微信网页客户端端)
复制代码
二、长连接
概念: TCP与服务器建立连接之后一直处于连接状态,直到最后不再需要服务的时候才断开连接优点: 1、传输数据快2、服务器能够主动第一时间传输数据到客户端缺点: 1、因为客户端与服务器一直保持这种连接,那么在高并发分布式集群系统中客户端数量会越来越多,占 用很多的系统资源2、TCP本身是一种有状态的数据,在高并发分布式系统会导致后台设计比较难做
复制代码
WebSocket,说说他的特点?
完了这是跟我杠上了,我依稀记得一些...,可以看出对基础考察得比较厉害
1、最大的特点就是服务端可以主动向客户端发送数据2、与 HTTP 协议有着良好的兼容性。默认端口是80和443,并握手阶段采用HTTP协议,因此握手时不容易屏蔽,能通过各种HTTP代理服务器。3、数据格式比较轻量,性能开销小,通信高效。4、可以发送文本,也可以发送二进制数据。5、没有同源限制,客户端可以与任意服务器通信。6、协议标识符是ws(如果加密,则为wss,加密层是TLS),服务器网址就是 URL。
说说三次握手四次挥手呗?
握手:(模拟甲请乙吃饭,我是这么理解的)
1、客户端发送一个SYN码给服务器,要求建立数据连接;(甲:来我家吃饭,给你一张SYN门卡)
2、服务器拿到SYN和自己处理一个SYN(标志);叫SYN+ACK(确认包);发送给客户端,可以建立连接;(乙:我收到你的门卡了,我也给你一张叫ASK的卡)
3、客户端再次发送ACK向服务器,服务器验证ACK没有问题,则建立起连接;(甲:来了啊进来吧!乙:出示你的ASK卡,我看看走错没,甲:这不是吗?快进来吧)
复制代码
挥手:
1、客户端发送FIN(结束)报文,通知服务器数据已经传输完毕;(甲:小声嘀咕..这货吃完了吧?该走了吧)
2、务器接收到之后,通知客户端我收到了FIN,发送ACK(确认)给客户端,数据还没有传输完成(乙:我听到你说的话了,你确定赶我走吗?但是我还没吃完哎!)
3、服务器已经传输完毕,再次发送FIN通知客户端,数据已经传输完毕(乙:我吃完了,别解释了,果然不爱了,我走了)
4、客户端再次发送ACK,进入TIME_WAIT状态;服务器和客户端关闭连接;(甲:把你的ACK还给你,把我家米都吃空了)
为什么建立连接是三次握手,而断开连接是四次挥手呢?
建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个 报文里发送给客户端。而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了 但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一 些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分 开发送,从而导致多了一次。
输入 URL 到页面渲染的整个流程
HTTP1.0、HTTP1.1 和 HTTP2.0 的区别
http缓存详解,http缓存推荐方案
看完这篇HTTP,跟面试官扯皮就没问题了
http请求头包含哪些东西?
HTTP Code
能说下ajax吗?
属性 | 描述 |
---|---|
onreadystatechange | 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。 |
readyState | 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。0: 请求未初始化1: 服务器连接已建立2: 请求已接收3: 请求处理中4: 请求已完成,且响应已就绪 |
status | 200: "OK" 404: 未找到页面 |
九种跨域方式实现原理(完整版)
设计模式
常用数据结构
4.vue
Vue路由守卫有哪些,怎么设置,使用场景等
常用的两个路由守卫:router.beforeEach 和 router.afterEach 每个守卫方法接收三个参数: to: Route: 即将要进入的目标 路由对象 from: Route: 当前导航正要离开的路由 next: Function: 一定要调用该方法来 resolve 这个钩子。 在项目中,一般在beforeEach这个钩子函数中进行路由跳转的一些信息判断。 判断是否登录,是否拿到对应的路由权限等等。
响应式原理
Vue是采用数据劫持配合发布者-订阅者模式,通过Object.defineProperty来()来劫持各个属性的getter和setter 在数据发生变化的时候,发布消息给依赖收集器,去通知观察者,做出对应的回调函数去更新视图。 具体就是: MVVM作为绑定的入口,整合Observe,Compil和Watcher三者,通过Observe来监听model的变化 通过Compil来解析编译模版指令,最终利用Watcher搭起Observe和Compil之前的通信桥梁 从而达到数据变化 => 更新视图,视图交互变化(input) => 数据model变更的双向绑定效果。
Vue中的computed和watch的区别?
1、computed:是一个有缓存的watcher,依赖的属性发生变化就会更新视图。 适用于计算比较消耗性能的计算场景。当表达式过于 复杂时,在模板中放入过多逻辑会让模板难以维护,可以将复杂的逻辑放入计算属性中处理 2、watch:没有缓存性,更多的是起到一个观察的作用。可以监听某些数据执行回调,当需要深度监听时,将deep:true开启即可。
双向绑定原理
通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终 利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化->视图更新。在 初始化vue实例时,遍历data这个对象,给每一个键值对利用Object.definedProperty 对data的键值对新增get和set方法,利用了事件监听DOM的机制,让视图去改变数据。
用过keep-alive吗,说说对它的理解?
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,有以下特性:
1、一般结合路由和动态组件一起使用,用于缓存组件。
2、提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹 配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高。
3、对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated, 当组件被移除时,触发钩子函数 deactivated。
组件中为什么data是一个函数
data() { return { message: "123", } } 原因:因为组件是需要被复用的,所以必须是一个函数,如果是一个对象,作用域没有分开,子组件 的data属性值会相互影响。是一个函数的话那么每个实例可以维护一份被返回对象的独立的拷贝,组 件之间的 data 属性值不会互相影响。
那为什么new Vue里data可以是一个对象?
new Vue({el: '#app',router,template: '<App/>',components: {App}
})原因:因为JS里的对象是引用关系,而且new Vue是不会被复用的,所以不存在引用对象的问题。
Virtual DOM了解吗?
Vue 常考基础知识点
https://juejin.cn/book/6844733763675488269/section/6844733763780345869
https://juejin.cn/book/6844733763675488269/section/6844733763784556552
5.react
6.性能优化
假设现在有1000条数据的长列表,说下不用分页你怎么优化加载?
重绘(Repaint)和回流(Reflow)
重绘和回流会在我们设置节点样式时频繁出现,同时也会很大程度上影响性能。
- 重绘是当节点需要更改外观而不会影响布局的,比如改变
color
就叫称为重绘 - 回流是布局或者几何属性需要改变就称为回流。
回流必定会发生重绘,重绘不一定会引发回流。回流所需的成本比重绘高的多,改变父节点里的子节点很可能会导致父节点的一系列回流。
以下几个动作可能会导致性能问题:
- 改变
window
大小 - 改变字体
- 添加或删除样式
- 文字改变
- 定位或者浮动
- 盒模型
并且很多人不知道的是,重绘和回流其实也和 Eventloop 有关。
- 当 Eventloop 执行完 Microtasks 后,会判断
document
是否需要更新,因为浏览器是 60Hz 的刷新率,每 16.6ms 才会更新一次。 - 然后判断是否有
resize
或者scroll
事件,有的话会去触发事件,所以resize
和scroll
事件也是至少 16ms 才会触发一次,并且自带节流功能。 - 判断是否触发了 media query
- 更新动画并且发送事件
- 判断是否有全屏操作事件
- 执行
requestAnimationFrame
回调 - 执行
IntersectionObserver
回调,该方法用于判断元素是否可见,可以用于懒加载上,但是兼容性不好 - 更新界面
- 以上就是一帧中可能会做的事情。如果在一帧中有空闲时间,就会去执行
requestIdleCallback
回调。
以上内容来自于 HTML 文档。
既然我们已经知道了重绘和回流会影响性能,那么接下来我们将会来学习如何减少重绘和回流的次数。
减少重绘和回流
- 使用
transform
替代top
<div class="test"></div>
<style>.test {position: absolute;top: 10px;width: 100px;height: 100px;background: red;}
</style>
<script>setTimeout(() => {// 引起回流document.querySelector('.test').style.top = '100px'}, 1000)
</script>
使用
visibility
替换display: none
,因为前者只会引起重绘,后者会引发回流(改变了布局)不要把节点的属性值放在一个循环里当成循环里的变量
for(let i = 0; i < 1000; i++) {// 获取 offsetTop 会导致回流,因为需要去获取正确的值console.log(document.querySelector('.test').style.offsetTop) }
不要使用
table
布局,可能很小的一个小改动会造成整个table
的重新布局动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用
requestAnimationFrame
CSS 选择符从右往左匹配查找,避免节点层级过多
将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。比如对于
video
标签来说,浏览器会自动将该节点变为图层。设置节点为图层的方式有很多,我们可以通过以下几个常用属性可以生成新图层
will-change
video
、iframe
标签
性能优化琐碎事
7.webpack/前端工程化
发布工具
https://juejin.cn/book/6844733763675488269/section/6844733763776315399
8.算法
一个树形结构数据,不用递归,如何用遍历去访问它?
9.综合问题/技术相关
组件封装
h5,和pc端有什么不同。
10.综合问题/职业相关
请描述一下 React 和 Vue的区别
1.设计思想vue的官网中说它是一款渐进式框架,采用自底向上增量开发的设计。react主张函数式编程,所以推崇纯组件,数据不可变,单向数据流,当然需要双向的地方也可以手动实现,比如借助 onChange 和 setState 来实现一个双向的数据流。
2.编写语法Vue推荐的做法是webpack+vue-loader的单文件组件格式,vue保留了html、css、js分离的写法React的开发者可能知道,react是没有模板的,直接就是一个渲染函数,它中间返回的就是一个虚拟DOM树,React推荐的做法是 JSX + inline style, 也就是把HTML和CSS全都写进JavaScript了,即'all in js'。
3.构建工具vue提供了CLI 脚手架,可以帮助你非常容易地构建项目。React 在这方面也提供了 create-react-app,但是现在还存在一些局限性,不能配置等等
4.数据绑定vue是实现了双向数据绑定的mvvm框架,当视图改变更新模型层,当模型层改变更新视图层。在vue中,使用了双向绑定技术,就是View的变化能实时让Model发生变化,而Model的变化也能实时更新到View。(这里我们可以继续深入讲解一下双向数据绑定的原理,我之前的文章手写Vue源码可参考)react是单向数据流,react中属性是不允许更改的,状态是允许更改的。react中组件不允许通过this.state这种方式直接更改组件的状态。自身设置的状态,可以通过setState来进行更改。(注意:React中setState是异步的,导致获取dom可能拿的还是之前的内容,所以我们需要在setState第二个参数(回调函数)中获取更新后的新的内容。)【这里如果你了解深入的话可以尝试描述一下React中setState的异步操作是怎么实现的,Vue中的更新是通过微任务等】
5.diff算法vue中diff算法实现流程:1.在内存中构建虚拟dom树2.将内存中虚拟dom树渲染成真实dom结构3.数据改变的时候,将之前的虚拟dom树结合新的数据生成新的虚拟dom树4.将此次生成好的虚拟dom树和上一次的虚拟dom树进行一次比对(diff算法进行比对),来更新只需要被替换的DOM,而不是全部重绘。在Diff算法中,只平层的比较前后两棵DOM树的节点,没有进行深度的遍历。5.会将对比出来的差异进行重新渲染react中diff算法实现流程:DOM结构发生改变-----直接卸载并重新createDOM结构一样-----不会卸载,但是会update变化的内容所有同一层级的子节点.他们都可以通过key来区分-----同时遵循1.2两点(其实这个key的存在与否只会影响diff算法的复杂度,换言之,你不加key的情况下,diff算法就会以暴力的方式去根据一二的策略更新,但是你加了key,diff算法会引入一些另外的操作)
React会逐个对节点进行更新,转换到目标节点。而最后插入新的节点,涉及到的DOM操作非常多。diff总共就是移动、删除、增加三个操作,而如果给每个节点唯一的标识(key),那么React优先采用移动的方式,能够找到正确的位置去插入新的节点。
vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制。
以上内容来自于Vue 和 React 的优点分别是什么?,大家说的越多理解的越深越好。我只说了其中的三点。
前端常用的数据请求格式有哪些?都有些什么特点?
这个问题在http中已经回答了一部分了,这里就在单独详细的描述一下使用场景
Get/Post/Delete/Patch/Put经常用的这五种,其他的就不说了通常:我们使用Get请求来获取数据我们使用Post请求来发送数据我们使用Put请求来更新数据我们使用Delete请求来删除数据我们使用Patch请求用于对资源应用部分修改。
Get和Post的区别:1.Get 请求能缓存,Post 不能2.Post 相对 Get 安全一点点,因为Get 请求都包含在 URL 里,(当然你想写到 body 里也是可以的),且会被浏览器保存历史纪录。Post 不会,但是在抓包的情况下都是一样的。4.URL有长度限制,会影响 Get 请求,但是这个长度限制是浏览器规定的,不是 RFC 规定的5.Post 支持更多的编码类型且不对数据类型限制
二次封装axios,描述一下你在项目中封装axios的思路和想法
关于axios等封装,我之前有一篇简易封装axios的文章,大家可以简单参考。通常来说,我们在二次封装axios,一般会引入UI组件的一些Message和Loading组件用来做提示信息。1.通过获取存储在浏览器端,或者是vuex中的token信息,判断是否跳转登录页面2.在获取到token的情况下设置自定义请求头部信息3.在响应事件中,根据返回的不同状态码,根据业务需求,使用switch判断跳转页面还是发出提示信息。4.封装请求和响应事件的返回结果,使用Promise封装。5.增加请求loading和提示信息。
简单版本大致如上,复杂版本需要根据业务进行对应的封装。
请用一个例子来形象的描述原型链
每个门派都有一个祖师爷。学徒在山上学艺,学成下山后谨记师门教导,施展一身武艺。恰逢一日对敌,面对敌人的怪异武功,师门好像未曾教过破解之法,便高喊一声祖师爷救我,刹那间一道白光降于头顶,祖师爷灵魂附体,一套精绝凌厉的拳法杀得敌人措手不及。但敌人也极是难缠,恐怕非要那门传说中从天而降的掌法才能制敌。你心中暗自着急,催促着祖师爷赶快发招,这时只听身内传来了祖师的声音:“MD这破掌法当年偷懒没学,我去把我师祖也叫来问问...”每个门派(FunctionX)都有一个祖师爷(prototype)。学徒(object)在山上学艺(= new FunctionX),学成下山后谨记师门教导,施展一身武艺(http://object.xxxobject.xxx)。恰逢一日对敌,面对敌人的怪异武功,师门好像未曾教过破解之法(object对象没有yyy方法),便高喊一声祖师爷救我,刹那间一道白光降于头顶,祖师爷(__proto__)灵魂附体,一套精绝凌厉的拳法杀得敌人措手不及(继续寻找原型中是否有yyy方法)。但敌人也极是难缠,恐怕非要那门传说中从天而降的掌法才能制敌。你心中暗自着急,催促着祖师爷赶快发招,这时只听身内传来了祖师的声音:“MD这破掌法当年偷懒没学,我去把我师祖也叫来问问...”(如果原型中没有yyy方法,则继续查找原型的原型,是谓原型链)
做过单点登录吗?了解他是怎么实现的吗?
实话实说没做过,但我看过一些关于单点登录的技术博客,大概整理原理如下:
概念:
简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,
用户只需要登录一次就可以访问所有相互信任的应用系统。列如:淘宝、天猫都属于阿里旗下的产品,当用户登录淘宝后,再打开天猫,系统便自动帮用户
登录了天猫,这种就是用单点登录实现的。
复制代码
流程:
1、用户访问A系统,系统A发现用户未登录,跳转至sso认证中心,并把自己的地址作为参数。
2、sso认证中心发现用户未登录,则引导用户到登录页面。
3、用户输入用户名和密码提交登录。
4、sso认证中心验证用户信息,创建用户->sso之间的会话(全局会话),同时创建授权令牌。
5、sso认证中心带着令牌跳转到A系统
6、系统A拿到令牌,去sso认证中心校验令牌是否有效。
7、sso认证中心校验令牌,返回有效,注册系统A。
8、系统A使用该令牌创建与用户的会话(局部会话),返回请求资源。
9、用户访问系统B。
10、系统B发现用户未登录,跳转至sso认证中心,也将自己的地址作为参数。
11、sso认证中心发现用户已登录,跳转到系统B,并附上令牌。
12、系统B拿到令牌,去sso认证中心校验令牌是否有效。
13、sso认证中心校验令牌,返回有效,注册系统B。
14、系统B使用该令牌创建与用户的局部会话,返回请求资源。
复制代码
注意:
1、局部会话存在,全局会话一定存在
2、全局会话存在,局部会话不一定存在
3、全局会话销毁,局部会话必须销毁
说下工作中你解决的觉得最难的事情是什么
还记得上篇文章中第一家公司我便遇到了这个问题,不知道怎么答才好,于是我问他们技术总监下次我该怎么答,这次我就根据上次总结后展开说了,我说我项目比较简单,技术上没有太难的东西,真的觉得难还是自己负责项目开发时,关于项目推进,如何与同事有效沟通等等展开说了。
所以说要多总结啊,别一个问题次次遇到都是不知道,没听过,不了解,面试过程中不管任何问题,只要你开头答了,都比你啥都不说要强,而且是强很多,这也是考你随机应变的一部分。
知道为什么很多公司要问这两个问题吗?因为这两个问题的答案,基本能给你以往经历定级了,有没有解决过特别复杂的问题,有没有技术深入研究,有没有代码追求等等在你的答案中都能体现出来。所以这两个问题一定要好好回顾自己过往经历,好公司必问!
谈谈你对于未来的规划
初步规划是想向全栈发展,再往后就是管理层。然后面试官就问我为什么想转全栈,我说为了提升自己的竞争力,我有关注招聘信息,从中我能得知现在行业需要什么技术,哪些能提升我的竞争力;面试官又问为什么有做管理的想法,这个我就直说了,同事朋友都觉得性格很好,有耐心,对于技术也有追求,很适合带人,当然,做管理不是技术好就可以了,只是他们的话在我脑中留下了一枚种子,如果真要往这方面发展,我需要学习的还很多。
说完这些面试官就对于我未来发展给出建议了,大致意思就是,学后端能拓展你对于前端问题的看法,比如很多问题在前端会遇到后端就不会,比如一个问题在前端做很麻烦,但在后端有专门的思路方法解决这件事,那么在你了解后端后,下次你遇到这样的问题,在你的脑中会潜移默化,我如何在前端中用后端现有思路解决它。其实总结面试官的话,永远学思想而不是学框架。
在上家公司有没有你觉得可以改进的事
说说你对于技术新旧的看法,如何抉择?
下面是我面试回答的观点,不一定对,大家就当个参考:
新不代表好,旧不代表过时,如何选择还是看它能为我们带来什么,优势是什么,缺点是什么,比如风险和不稳定性。举个例子,JQ过时吗?其实站在DOM操作层面,JQ在各浏览器间优秀的兼容性以及操作便捷性,无疑是一个不错的选择,它为什么"过时"呢?这是因为目前主流框架vue,angular,react已经不需要我们过多关注视图层,操作dom的需求少了这才导致JQ"过时"。
如何抉择一个框架呢?我觉得得看它与我们需求的匹配度,拿bootstrap举例,很多人不爱使用bootstrap,觉得我自己也能做适配,何必用它。这就得看具体需求了,如果我们一个项目是要做到PC,平板,移动端自动适配,用bootstrap就是首选,因为这个框架主打的就是栅格化系统一套样式实现响应式,让你自己用媒体查询自己写,那不得写疯。但如果我们兼容的只是部分容器,需求不大,这时候用bootstrap就有种杀鸡焉用牛刀的感觉,很不值得,所以怎么选还是得根据需求而定。
为什么从上家公司离职?
两个方面,一是公司开发需求少,有种温水煮青蛙的感觉,会很焦虑,害怕自己被这个行业淘汰,所以顶着疫情也要选择离职。第二个方面是孤独,公司技术氛围不是很好,大家对于技术热情不是很高,我会学很多有用的知识,想讨论却发现没一个人可以交流,因为渴望交流,所以养成了写博客的习惯,与网上同行们交流。
如何写好一封简历
面试常用技巧
前端安全
ES6新特性
1.ES6引入来严格模式变量必须声明后在使用函数的参数不能有同名属性, 否则报错不能使用with语句 (说实话我基本没用过)不能对只读属性赋值, 否则报错不能使用前缀0表示八进制数,否则报错 (说实话我基本没用过)不能删除不可删除的数据, 否则报错不能删除变量delete prop, 会报错, 只能删除属性delete global[prop]eval不会在它的外层作用域引入变量eval和arguments不能被重新赋值arguments不会自动反映函数参数的变化不能使用arguments.caller (说实话我基本没用过)不能使用arguments.callee (说实话我基本没用过)禁止this指向全局对象不能使用fn.caller和fn.arguments获取函数调用的堆栈 (说实话我基本没用过)增加了保留字(比如protected、static和interface)2.关于let和const新增的变量声明3.变量的解构赋值4.字符串的扩展includes():返回布尔值,表示是否找到了参数字符串。startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
5.数值的扩展Number.isFinite()用来检查一个数值是否为有限的(finite)。Number.isNaN()用来检查一个值是否为NaN。
6.函数的扩展函数参数指定默认值
7.数组的扩展扩展运算符
8.对象的扩展对象的解构
9.新增symbol数据类型10.Set 和 Map 数据结构 ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。 Set 本身是一个构造函数,用来生成 Set 数据结构。Map它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
11.ProxyProxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。Vue3.0使用了proxy
12.PromisePromise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。特点是:对象的状态不受外界影响。一旦状态改变,就不会再变,任何时候都可以得到这个结果。
13.async 函数 async函数对 Generator 函数的区别:(1)内置执行器。Generator 函数的执行必须靠执行器,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。(2)更好的语义。async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。(3)正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。(4)返回值是 Promise。async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
14.Class class跟let、const一样:不存在变量提升、不能重复声明...ES6 的class可以看作只是一个语法糖,它的绝大部分功能ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
15.ModuleES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。import和export命令以及export和export default的区别
前端 100 问
简历
面试指南
Typescript
2021年web前端基础面试题相关推荐
- web前端基础面试题
目前在从事前端工作,特别总结写面试题知识供大家学习,需要前端面试题答案的同学,可以加我创建的前端群 937268047 一.选择题 HTTP是() (A)文件传输协议 (B)超文本传输协议 (C)可扩 ...
- 2021年web前端开发视频教程,自学web前端开发技术,全套web前端学习路线笔记
2021年web前端开发视频教程,自学web前端开发技术,全套web前端学习路线笔记 [导读]:初学web前端的小伙伴经常会遇到的问题,1.没方法 2.没资源 3.没经验,不知道从何开始 ,代码哥(D ...
- Web前端基础知识整理
1. 前端基础知识 文件分类 XML(扩展标记语言) 装载有格式的数据信息,用于各个框架和技术的配置文件描述 特点: 扩展名为.xml 内容区分大小写 标签要成对出现,形成容器,只能有一个 标签按正确 ...
- Web前端经典面试题-JavaScript
Web前端经典面试题-JavaScript 看看银行卡余额,看看工资条,看看房价,动力就来了,大二狗,加油~~ JavaScript 原型链.类.继承.作用域.闭包.js运行机制/单线程.js数据类型 ...
- 2018最新Web前端经典面试试题及答案
本篇收录了一些面试中经常会遇到的经典面试题以及自己面试过程中遇到的一些问题,并且都给出了我在网上收集的答案.马上就要过春节了,开年就是崭新的一年,相信很多的前端开发者会有一些跳槽的悸动,通过对本篇知识 ...
- 2014年最新web前端开发面试题
2014年最新web前端开发面试题 本文是一份非常不错的2014年web前端开发工程师的面试题集锦,并附有参考答案,推荐大家参考下. 试题目录: HTML 部分 CSS 部分 JavaScript 部 ...
- 前端基础面试题(JS部分)
1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined.Null.Boolean.Number.String 值类型:数值.布尔值.null.und ...
- 2021年web前端发展方向有哪些
一年转瞬即逝,仅仅一年的时间,就能发生很多事情,近几年web前端行业越来越受到大家的关注,很多人都想看看2021年web前端发展方向有哪些?下面来看看小编详细的介绍. 2021年web前端发展方向有哪 ...
- Web前端JQuery面试题(三)
Web前端JQuery面试题(三) 1.怎么阻止冒泡过程? stopPropagation(); // 阻止冒泡过程 2.ready()方法和onload()方法的区别? onload()方法要等页面 ...
最新文章
- 【综述专栏】图神经网络综述
- SQL Server基础操作(此随笔仅作为本人学习进度记录二)
- inotify-tools使用方法介绍
- Linux下监控磁盘io,如何在Linux下监控磁盘IO?
- 跨平台 获取系统信息的python库 http://support.hyperic.com/disp
- 嵌入式之NB-IoT开发与应用01【移动通信网络发展概述、NB-IoT应用案例、物联网生态系统-解决方案、智慧消防项目需求分析及系统设计】
- linux mrtg 进程名称,Linux上的MRTG流量监控中心
- Rusty String
- RabbitMQ 入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)
- 宝塔 windows 2012 配置 ftp 允许 fileZilla 连接
- db2存储过程 可以使用游标循环嵌套吗_DB2存储过程使用动态游标的例子
- mysql数据库 day06
- Android 打造编译时注解解析框架
- php redis zset 延迟队列_用PHP+Redis实现延迟任务,实现自动取消订单
- linux内核之设备驱动
- PE启动盘安装操作系统
- si24r1程序_SI24R1技术支持--程序 射频识别(radio frequency indentificationx) - 下载 - 搜珍网...
- 我们为你精选了一份Jupyter/IPython笔记本集合 !(附大量资源链接)-上篇
- 搭建图像搜索引擎(之0):霍比特人直方图
- 大神教你如何用 Python 快速分析你的微信好友
热门文章
- 计算机操作员考评标准,计算机操作员职业技能鉴定标准高级.doc
- Java回炉之File
- python最简单的爬取邮箱地址_python3爬取网页中的邮箱地址
- 照度/感光度(Lux)
- 怎样用网址查询微信公众号的二维码
- 在未提供官方驱动的Windows平板上安装Win10且完美驱动的解决方案
- Elastic:我应该使用 Logstash 或是 Elasticsearch ingest 节点?
- mysql连接数尖刺激增_mysql最大连接数max_connections
- 豆瓣读书top250数据爬取与可视化
- 嵌入式大牛开发经验心得