面经

173 阅读8分钟

1、讲一下盒模型,普通盒模型和怪异盒模型有什么区别?

标准的盒子模型的大小是:content(区域内容大小)+padding(内边距)+border(边框)+margin(外边距);

注:标准盒子的初始设置宽高大小不包含padding、border和margin的大小。

怪异的盒子模型的大小是:content(区域内容大小)+margin(外边距);

注:怪异盒子的初始设置宽高大小包含padding、border大小在内,但不包含margin的大小。

2、CSS如何实现垂直居中?

1、通过vertical-align:middle实现CSS垂直居中。

2、通过display:flex实现CSS垂直居中。

3、通过伪元素:before实现CSS垂直居中。

4、通过display:table-cell实现CSS垂直居中。

5、通过隐藏节点实现CSS垂直居中。

6、已知父元素高度通过transform实现CSS垂直居中。

7、到垂直居中的位置。

8、通过line-height实现CSS垂直居中。

blog.csdn.net/m0_52409770…

3、伪类和伪元素的区别是什么?

伪类和伪元素的根本区别在于:

它们是否创造了新的元素(抽象)。从我们模仿其意义的角度来看,如果需要添加新元素加以标识的,就是伪元素,反之,如果只需要在既有元素上添加类别的,就是伪类。

伪类的例子有:

:hover
:active
:first-child
:visited
等。

伪元素的例子有:

:first-line
:first-letter
:after
:before

4、call bind apply的区别?(场景:两个arr合并)(箭头函数是否变化)(判断是否array)

1.apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;

2.apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;

3.apply 、 call 、bind 三者都可以利用后续参数传参;

bind是返回对应函数,便于稍后调用;apply、call则是立即调用 。

区别:

call和apply的功能相同,区别在于传参的方式不一样

bind 和call/apply 有一个很重要的区别,一个函数被 call/apply 的时候,会直接调用,但是bind 会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数

5、防抖节流的概念?实现防抖和节流(场景:连续点击)

juejin.cn/post/707417…

防抖

防抖具体指的是某个函数在某段时间内,无论触发了多少次回调,都只执行最后一次。假如我们设置了一个等待时间 3 秒的函数,在这 3 秒内如果遇到函数调用请求就重新计时 3 秒,直至新的 3 秒内没有函数调用请求,此时执行函数,不然就以此类推重新计时

节流:

函数节流指的是某个函数在一定时间间隔内(例如 3 秒)只执行一次,在这 3 秒内 无视后来产生的函数调用请求,也不会延长时间间隔。3 秒间隔结束后第一次遇到新的函数调用会触发执行,然后在这新的 3 秒内依旧无视后来产生的函数调用请求,以此类推。函数节流非常适用于函数被频繁调用的场景,例如:window.onresize() 事件、mousemove 事件、上传进度等情况。

6、如何判断数组(可换成:遍历的方法、reduce参数,求平均数)

zhuanlan.zhihu.com/p/80405749 字符串方法

www.jianshu.com/p/ec79c4e47… 数组方法

// ES6中增加的数组方法
Array.isArray()


// 使用constructor判断
function isArray(arr) {
    return arr.constructor.toString().indexOf("Array") > -1;
}


function isArray(arr) {
    return arr.constructor === Array;
}


// 用instanceof判断
function isArray(arr){ 
    return arr instanceof Array; 
}

7、如何理解闭包(怎么实现定时器、延时器函数句柄传参)

对闭包的理解:

  1. 什么是闭包?函数和函数内部能访问到的变量的总和,就是一个闭包。

  2. 如何生成闭包? 函数嵌套 + 内部函数被引用。

  3. 闭包作用?隐藏变量,避免放在全局有被篡改的风险。

  4. 使用闭包的注意事项?不用的时候解除引用,避免不必要的内存占用。

为什么有闭包的这种特性:如果形成闭包,外部函数执行完后,其中的局部变量可能被内部函数使用,所以不能销毁,因此内部函数能一致访问到这些局部变量,直到引用解除。

为什么需要闭包?隐藏变量,避免放在全局有被篡改的风险。

闭包的缺点:使用时候不注意的话,容易产生内存泄漏。

8、使用new创建对象的过程是什么样的(各个函数对象 显示原型prototype和隐式原型__proto__的关系,constructor)

  1. 首先创建了一个新的空对象
  2. 设置原型,将对象的原型设置为函数的prototype对象。
  3. 让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
  4. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

9、Typescript中type和interface的区别是什么

www.jb51.net/article/243…

10、讲讲Typescript中的泛型?

www.jianshu.com/p/8c623d7fb…

11、比较一下history和hash这两种路由

juejin.cn/post/711410…

12、Vue.nextTick的实现

  1. 接收callback放入callbacks中
  2. 根据当前的浏览器环境选用对用的异步事件API 创建一个异步执行函数timerFun,选用的优先级如下
  • Promise.then
  • MutationObserver
  • setImmediate
  • setTimeout
  1. 执行timerFun将callBacks注册进事件队列
  2. 事件循环执行到对应的宏任务或者微任务时依次执行callbacks中的回调

13、react diff算法

React的diff算法基于两个假设:

1、不同元素的类型会产生不同的树

2、开发者可以通过key prop标识一个元素在不同的渲染下可以保持稳定(及相同key的元素不需要更新整个元素,不同的key需要更新整个元素)

基于上述假设,React认为在视图更新前后,如果两个节点的Tag名(对于原生标签)或者组件(对于自定义组件)相同,则它们是同一个节点,而且如果是不同的根节点,那么子节点也不需要对比,直接用新树替换掉旧的树即可。

对比的过程

1、当一个组件触发更新(setState),则React会diff以这个组件为根节点的整个虚拟DOM树,对比更新后的虚拟DOM和更新前的虚拟DOM。

2、如果两个节点不同,则用新的节点替换掉旧的节点;如果两个节点相同(假设为oldNode和newNode),则对比它们的属性、innerText和子节点。

3、如果oldNode有某个子节点someOldChild,而newNode没有这个子节点(即newNode没有一个子节点,和someOldNode有相同的tag名、自定义组件引用或者key值),则删掉someOldChild;如果newNode有某个子节点somNewChild,而oldNode没有,则添加someNewChild;如果oldNode和newNode都有某个节点someChild,则将其移动到正确的位置,并递归地进行对比工作,即以someChild为根节点对比新旧两棵虚拟DOM树。

从上面的对比过程可以看出,React的diff(其实Vue也是一样)并不会考虑到节点跨层移动的情况,因此有些观点认为React的对比过程可以描述为“按层比较”(level by level)。

14、Cookie、sessionStorage、localStorage 的区别

相同点

  • 存储在客户端

不同点

  • cookie数据大小不能超过4k;sessionStorage和localStorage的存储比cookie大得多,可以达到5M+
  • cookie设置的过期时间之前一直有效;localStorage永久存储,浏览器关闭后数据不丢失除非主动删除数据;sessionStorage数据在当前浏览器窗口关闭后自动删除
  • cookie的数据会自动的传递到服务器;sessionStorage和localStorage数据保存在本地

15、介绍下304过程

  • a. 浏览器请求资源时首先命中资源的Expires 和 Cache-Control,Expires 受限于本地时间,如果修改了本地时间,可能会造成缓存失效,可以通过Cache-control: max-age指定最大生命周期,状态仍然返回200,但不会请求数据,在浏览器中能明显看到from cache字样。

  • b. 强缓存失效,进入协商缓存阶段,首先验证ETagETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。服务器根据客户端上送的If-None-Match值来判断是否命中缓存。

  • c. 协商缓存Last-Modify/If-Modify-Since阶段,客户端第一次请求资源时,服务服返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间。再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。