当前位置: 首页 > 面试经验 >

途虎养车前端面经帖复习Ⅰ(3463字预警)

优质
小牛编辑
191浏览
2023-03-28

途虎养车前端面经帖复习Ⅰ(3463字预警)

编者按:
以下面经题目来自牛客网其他作者,已注明原帖来源。
(原帖作者若不允许搬运,可私聊我进行删除处理)
答案由本人整理,不确保完全正确,有异议可评论区指出,感恩的心


一、原帖:9.27途虎前端(37min)

1、输入url发生了什么?

①浏览器的UI线程实时捕捉输入的内容,如果输入的不是网址或者协议不合法就使用浏览器默认的搜索引擎进行搜索(此处还会检查有没有出现非法字符,有的话会对非法字符进行转义)
②在回车之前,还会执行一次当前页面的beforeunload事件,可以让页面退出之前执行一些数据清理工作,或者,有表单没有提交的情况提示用户是否确认离开
③然后下一步浏览器进程会通过IPC把URL发送给网络进程,然后网络进程要先找本地缓存,如果有缓存,并且没有过期,就不发送请求,直接拿来解码再开始渲染流程
④如果没有缓存或者缓存过期,再开始解析URL,解析出要请求的服务器 的IP地址,把请求需要的协议、域名、端口、路径等信息解析提取出来
⑤根据解析出来的域名,进行DNS解析(递归+迭代),找到要请求的服务器的IP地址
⑥拿到IP地址后,三次握手建立TCP连接,https的话还需要进行TLS加密协议的握手过程
⑦连接建立成功之后,浏览器会构建请求行、cookie等数据附加到请求头中,发给服务器,服务器接受请求并解析,如果没有对应的资源就404;否则检查HTTP请求头有没有包含协商缓存信息(前面命中强缓存且已过期的话就会走这个步骤),如果验证缓存没有更新,过期的缓存依然可以使用,就返回304和空响应体;如果没有缓存或者资源更新了,就读取完整请求并准备http响应,进行查询数据库等操作,返回200和查询到的资源
⑧浏览器接收到响应数据之后,如果是http1.1以下则直接关闭连接,否则双方都可以根据情况选择关闭TCP连接或者保留重用,现在浏览器默认都会保持连接(keep-alive)
⑨拿到资源后根据资源类型(Content-Type)决定如何处理,如果浏览器判断是下载文件,那么请求会被提交给浏览器的下载管理器,同时URL请求流程就结束了,否则网络线程会通知UI线程,然后UI线程会创建一个渲染器进程来准备渲染页面
⑩渲染

2、浏览器渲染页面的过程

3、加载js和css会不会阻塞页面渲染

js加defer和async的情况
css用link和@import的情况
link标签引入css资源时在火狐浏览器中是异步加载的,在谷歌浏览器中是同步加载的。
但如果是通过style标签引入样式,则不论何种浏览器,均为同步加载。
@import是在网页完全载入后才加载,在关键路径上创造了更多的网络请求,阻塞渲染时间,影响浏览器的并行下载,多个@import导致下载顺序紊乱。

4、重排重绘

重排:当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。
①添加、删除可见的dom
②元素的位置改变
③元素的尺寸改变(外边距、内边距、边框厚度、宽高等几何属性)
④页面渲染初始化
⑤浏览器窗口尺寸改变
重绘:是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
如何减少reflow、repaint?
①不要一条一条的修改DOM的样式,可以先定义好css的class,然后修改DOM的className。
②不要把DOM结点的属性值放在一个循环里当成循环里的变量。
③为动画的HTML元件适用fixed或absolute的position,那么修改他们的css是不会reflow

5、深浅拷贝

浅拷贝:基本数据类型、扩展运算符()、slice()、concat()、Object.assign()
深拷贝:JSON.parse(JSON.stringify())、手写深拷贝、lodash

6、闭包

闭包就是如果一个函数访问它外部(父级及父级以上作用域)的变量,这个函数就是一个闭包。
闭包内的变量不会被回收;实现了对其他函数内部变量的访问

7、防抖节流实现思路

防抖:
function debounce(fn, wait) {
  let timer = null
  return function () {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
    timer = setTimeout(() => {
      fn.call(this, arguments)
    }, wait)
  }
}
节流:
//时间戳版
function throttle(fn, wait) {
  let date = Date.now()
  return function () {
    let now = Date.now()
    if (now - date > wait) {
      fn.call(this, arguments)
      date = now
    }
  }
}
//定时器版
function throttle(fn, wait) {
  let timer = null
  return function () {
    if (!timer) {
      timer = setTimeout(() => {
        fn.call(this, arguments)
        timer = null
      }, wait)
    }
  }
}

8、Object和map

共同点:键值对的动态集合,支持增删
不同点:
①构造方式不同
//map
const map = new Map()
const map1 = new Map([['a',1],['b',2]])
//obj
const obj = new Object()
const obj1 = Object.create()
②object键的类型必须是String或者Symbol、map键的类型可以是任意类型
③object中key是无序的,map中可以是有序的,按照插入的顺序返回
④object只能通过Object.key()方法或for in统计数量,map有map.size
⑤object可以通过点或中括号访问属性,map用map.get()
⑥object不具备Iterator特性,不能for of遍历,map的keys()、values()、entries()都具有迭代器
⑦object可以用JSON.stringify()进行序列化,map只能转化成JSON,不能被parse解析
⑧应用场景:object做数据存储,需要序列化时使用;map频繁更新键值对,key类型未知时使用

9、三次握手四次挥手

三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包,以确认双方的接收能力和发送能力是否正常,为后面的可靠性传送做准备。

终止TCP连接需要发送四个包,因此称为四次挥手,客户端或服务端均可主动发起挥手动作。

10、http和https的区别

①https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
②http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
③http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
④http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

11、报文组成

HTTP报文分为请求报文和响应报文。
请求报文会向Web服务器请求一个动作,响应报文会将请求的结果返回给客户端。
请求和响应报文的基本报文结构相同。
//请求报文
<method> <request-URL> <version>
<headers>
<entity-body>
//响应报文
<version> <status> <reason-phrase>
<headers>
<entity-body>

12、状态码

1XX(信息性状态码)表示接收的请求正在处理
2XX(成功状态码)表示请求正常处理完毕
3XX(重定向状态码)表示需要进行附加操作以完成请求
4XX(客户端错误状态码)表示服务器无法处理请求
5XX(服务器错误状态码)表示服务器处理请求出错

13、堆和栈

①堆栈空间分配区别(操作系统):
栈由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
堆 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
②堆栈缓存方式区别:
栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;
堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
③堆栈数据结构区别:
栈是一种先进后出(FILO)的数据结构;
堆可以被看成是一棵树,如:堆排序。
最大堆和最小堆?
最大堆:根结点的键值是所有堆结点键值中最大者,且每个结点的值都比其孩子的值大。
最小堆:根结点的键值是所有堆结点键值中最小者,且每个结点的值都比其孩子的值小。

14、进程和线程

进程:一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程。
线程:进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。
进程和线程的区别:
①进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)
②进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
③线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC) 进行。
④但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。

二、原帖:途虎养车前端面经(一面二面hr面)

1、手撕:统计字符串每个字符个数是否相同,返回true or false

function getRepeat(arr) {
  let res = arr.reduce((p, k) => {
    p[k] ? p[k]++ : p[k] = 1
    return p
  }, {})
  let same = []
  for (let key in res) {
    same.push(res[key])
  }
  if ([...new Set(same)].length <= 1) {
    return true
  } else {
    return false
  }
}
let arr = [2, 3, 4, 5, 'a', 2, 3, 2, 'a', 'd', 'b']
console.log(getRepeat(arr))

三、原帖:途虎前端一面

1、手写防抖节流

同上文 一、7、

2、手写对象扁平化

const flatten = (arr) => {
  return arr.reduce((pre, cur) => {
    return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
  }, [])
}

3、setTimeout实现setInterval

setTimeout(function f() {
    setTimeout(f, interval);
}, interval)

4、手写ajax(使用promise封装)

function getJSON(url) {
  let promise = new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest()
    xhr.open("GET", url, true)
    xhr.onreadystatechange = function () {
      if (this.readyState !== 4) return
      if (this.status === 200) {
        resolve(this.response)
      } else {
        reject(new Error(this.statusText))
      }
    }
    xhr.onerror = function () {
      reject(new Error(this.statusText))
    }
    xhr.responseType = "json"
    xhr.setRequestHeader("Accept", "application/json")
    xhr.send(null)
  })
  return promise
}

5、水平垂直居中方法

①flex布局,父元素display:flex; justify-content:center; align-items:center;
②父元素position:relative; 子元素position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
③父元素position:relative; 子元素position:absolute; left:0; top:0; bottom:0; right:0; margin:auto;
④文字的话, text-align:center; line-height 和 height 相等

6、promise allsettled

参考: 什么是 Promise.allSettled() !新手老手都要会?

7、BFC触发方法,高度塌陷怎么解决

触发BFC的方法:
①根标签html本身就是一个BFC;②float不为none;③position为absolute或fixed;④overflow为非visible;⑤display 设置为table-cell、table-caption、flex、inline-block、inline-flex
高度塌陷怎么解决?打开BFC
①给父元素添加固定高度;②给父元素添加overflow:hidden; ③父元素结尾添加新的div标签并设置clear:both; ④父元素设置overflow:auto; ⑤父元素::after设置content: ''; display: inline-block; height: 0; clear: both; visibility: hidden;

个人笔面记录汇总:zkey秋招之旅 前端笔面汇总-附时间线

参见专栏:zkey秋招之旅

(持续更新,欢迎订阅~

#前端##面经##校招##23届秋招笔面经##2023一起秋招吧#
 类似资料: