热乎的百度前端面试题及答案分享

在这次找工作的过程中,百度整体的流程还是比较规范的,虽然因为第一次去百度大厦的时候被HR告知一面面试官因为会议原因要临时取消面试,改约其他时间。但是之后来到和所有的面试官聊天的过程中,还是感受到了大厂范儿。

相较于其他公司喜欢问原理、问机制,百度的几面中更关注的是你在工作中是如何运用你所掌握的框架知识的,工作中是如何平衡业务和技术的,会通过一些工作中很实际的问题来一层层的深入讨论,这点我觉得非常好。

下面主要看一下百度线下测试题部分,看看百度更关注一个前端的基本素养是什么。

样式相关

1.1 假设有如下的 DOM 结构 & 样式 ( ⼩提示, 可以先往下看, 然后再回来看这⼀⼤坨 css )

<style>
body {
  background: #fff !important;
 }
.root {
  border: 3px #000 solid;
  width: 200px;
 }
.root div {
  box-sizing: border-box;
  border: 1px #000 solid;
  background-color: #fff;
 }
.div-a {
  position: relative;
  z-index: 100;
  top: 50px;
  width: 200px;
  height: 100px;
 }
.div-b {
  position: absolute;
  z-index: 300;
  top: 80px;
  width: 100px;
  height: 50px;
 }
.div-c {
  position: absolute;
  z-index: 200;
  width: 50px;
  height: 100px;
 }
</style>

<div class="root"> 
  <div class="div-a"> 
    <div class="div-b"></div>
  </div>
  <div class="div-c"></div>
</div>

问题

  • 请问以上 HTML ⽚段, 对应以下的哪⼀个渲染效果?
  • 请简要分析⼀下你的推导思路?
    • 提示, 这个⼩问是必答的, 我们需要参考你的实际推导依据

作答

选B。

⾸先,针对 root ⾼度,由于 root 下的元素只有 div-a 是 relative ,在⽂档流中;⼜因为所有 div 的盒模型是使⽤的标准盒模型,所以 root 的⾼度就等于 div-a 的⾼度 200px + 其上下边框的⾼度 3px*2 = 206px ;

然后, div-a 相对其正常位置向下偏移 50px (top: 50px) , div-b 是绝对定位,其定位是相对于⽗级 div-a 进⾏的,向下偏移 80px (top:80px) ,由此可以排除C、D选项。

A、B选项中的不同点在于针对 div-c 和 div-b 的 z-index ,由于 div-b 的⽗级元素 div-a 的 z-index 为 100px ,根据从⽗规则,所以 div-b 的 z-index 会被降级,⽽ div-c 的 z-index 值⼤于 div-a 的 z-index ,所以 div-c 在 div-b 的上⾯。故选B。

1.2 简要介绍⼀下, 你在项⽬中, 如何管理各个元素的 z-index ?

  • 制定使⽤z-index的规范,⽐如 popover,modal,colorpicker 之类的组件,按照组件特性指定其层级的⾼低规范。另外业务布局中如果⽤到了z-index,尽量控制其层级为较低的规范内,如布局中的z-index尽量使⽤1xx,弹出层类的组件使⽤2xx等。
  • 全局维护⼀个获取z-index的⽅法,每次调⽤时数值递增1

1.3 简要介绍⼀下, 你如何在项⽬中管理样式的? 如何避免不同⻚⾯ / 模块中, 样式的互相影响 ?

  • ⽬前项⽬中使⽤的是 BEM 规则,通过区分模块和元素来进⾏样式命名。
  • 通过 css modules 将css进⾏分模块管理。

⽹络相关

2.1 : 什么是同源策略和跨域? 解决跨域的⽅法有哪些 ?

同源策略是指协议、端⼝、域名相同,也就是在同⼀个域中。

⾮同源受到的限制有:cookie⽆法读取、dom⽆法获取、ajax请求⽆法发送。

跨域:两个不同域(协议、端⼝、域名不同)之间进⾏请求。

解决跨域的⽅法:

  • JSONP,通过动态创建⼀个script标签,script标签的src属性是没有跨域的限制的。
  • cors,服务端在response时增加⼀些头信息:

必需项, 值为请求头中的 Origin 的值.

  • Access-Control-Allow-Credentials:true

可选项, 值为boolean, 表示是否允许浏览器发送cookie, 需要在服务器配置.

  • Access-Control-Allow-Methods:

必需项, 允许跨域请求的请求⽅式.

  • Nginx做反向代理
  • 开发环境跨域使⽤ webpack-dev-server 的 proxy

2.2 : 列举⼀下 HTTP 中关于 "资源缓存" 的头部指令 (Head) 有哪些 ? 并简要介绍⼀下设置的规则 ?

强制缓存

  • Expires 指定⼀个缓存的过期时间,如果当次请求的资源在该过期时间之前,则命中缓存。缺点是

因为这个时间是⼀个绝对时间,所以当客户端本地时间被修改后,服务器与客户端时间偏差变⼤会 导致缓存混乱。

  • Cache-Control ⼀般通过 max-age 指定⼀个相对时间,单位是秒。优先级⾼于 Expires 。其他常⽤

的取值有:

  • public 表示响应可以被任何对象缓存
  • private 表示只能被单个⽤户缓存,⾮共享的,不能被代理服务器缓存
  • no-cache 强制所有缓存了该响应的⽤户,在使⽤已缓存的数据钱,发送待验证器的请求到服务器。
  • No-store 禁⽌缓存

协商缓存

若未命中强缓存,则浏览器会将请求发送⾄服务器。服务器根据http头信息中的Last-Modify/If-ModifySince或Etag/If-None-Match来判断是否命中协商缓存。如果命中,则http返回码为304,浏览器从缓存 中加载资源。

  • Last-Modify/If-Modify-Since 浏览器第⼀次请求⼀个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是⼀个时间标识该资源的最后修改时间,当浏览器再次请求该资源时,发送的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到IfModify-Since后,根据资源的最后修改时间判断是否命中缓存。
  • ETag/If-None-Match ETag可以保证每⼀个资源是唯⼀的,资源变化都会导致ETag变化。ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。

2.3 : 简要解释⼀下 301, 302, 304 的区别 ?

301 永久性重定向。该状态码表示请求的资源已经被分配了新的URI,并且以后使⽤资源现在所指的URI。并且根据请求的⽅法有不同的处理⽅式。

302 临时性重定向。该状态码表示请求的资源已被分配了新的URI,希望⽤户本次能使⽤新的URI访问。

304 该状态码表示客户端发送附带条件请求时,服务器端允许请求访问资源,但未满⾜条件的情况。

304状态码返回时,不包含任何响应的主题部分。附带条件的请求指的是采⽤GET⽅法的请求头中包含:If-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任⼀⾸部。

JS & 算法相关

3.1 : 请说明以下程序打印出什么结果, 并简要说明推导依据

const result = ['1', '3', '10'].map(parseInt);
// 这⾥会打印出什么呢? 
console.log( result );

作答

打印结果是[1, NaN, 2] 因为map的参数是

function(current, index, arr) { // 当前元素值,当前元素索引值,数组本身
}

parseInt的参数是:

parseInt(str, radix) // 解析的字符串,⼏进制(若省略或为0,则以10进⾏解析,若⼩于2或者⼤于36,则返回NaN)

所以该题展开来写:

const result = ['1', '3', '10'].map(function(cur, index, arr) {
return parseInt(cur, index);
});
// 执⾏过程:
// parseInt('1', 0) -> 1
// parseInt('3', 1) -> NaN
// parseInt('10', 2) -> 2

3.2 : 请修改以下代码, 使最后能顺序打印出 1, 2, 3, 4, 5

for (var i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  }, 1000);
}
  • 要求: 每个数字之间, 间隔时间为 1秒(提示, 好好审题哟)

作答:

const myPromise = num => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(num)
      }, 1000)
    })
 }

async function test() {
  for (let i = 0; i < 5;) {
    i++;
    console.log(await myPromise(i))
  }
 }
test();

3.3 : 按照如下要求实现 process ⽅法

  • 取得两个数组⾥相同的部分, 并去重
  • 然后按照从⼩到⼤顺序排序, 最后结果返回 (注意, 是返回结果, 不是把结果打印出来)
const arrayA = [4, 2, 1, 2, 5];
const arrayB = [2, 3, 1, 6];
function process(arrayA, arrayB) {
// 这⾥是你实现代码的地⽅
}
/*
应该返回 [1, 2]
*/
process(arrayA, arrayB);

作答部分

第一种:

function process(arrayA, arrayB){
  return arrayA
    .filter((v) => arrayB.includes(v))
    .filter((v, i, arr) => arr.indexOf(v) === i )
    .sort((a, b) => a-b);
}

第⼆种:

function process(arrayA, arrayB) {
  const set = new Set();
  while(arrayA.length > 0) {
    const ele = arrayA.pop();
    if (arrayB.includes(ele)) {
      set.add(ele);
    }
  }
  return [...set].sort((a,b) => a - b);
}

3.4 (附加题) : ⼩明要上⼀个⻓阶梯, 这个阶梯共有 N 个台阶, 假设⼩明每次能上⼀个台阶, 也能上两个台阶, 请问⼩明上这个阶梯, 总共有⼏种⾛法?

  • 你的⽬标是实现⼀个⽅法
  • 输⼊是⼀个 "数字 n (有⼏个台阶)"
  • 输出是⼀个 "数字 ( 代表总共有⼏种⾛法)"
/*
例如,
 n = 1, return 1 (⽅法1: 1台阶)
 n = 2, return 2 (⽅法1: 1台阶&1台阶, ⽅法2: 2台阶)
 n = 3, return 3 (⽅法1: 1台阶*3次, ⽅法2: 1台阶&2台阶, ⽅法3: 2台阶&1台阶)
*/
function step(n) {
// 这⾥是你实现代码的地⽅
}

作答

(典型的斐波那契数列)

递归解法:

function step(n) {
  if (n <= 0) {
    throw new Error("param err");
    return -1;
  }
  if (n == 1) return 1;
  if (n == 2) return 2;
  return step(n - 1) + step(n - 2);
}

⾮递归解法:

function step(n) {
  if (n <= 0) {
    throw new Error("param err");
    return -1;
  }

  if (n === 1) return 1;
  if (n === 2) return 2;

  let nMinusOne = 2,
  nMinusTwo = 1,
  timeN = 0;

  for (let i = 3; i <= n; ++i) {
    timeN = nMinusOne + nMinusTwo;
    nMinusTwo = nMinusOne;
    nMinusOne = timeN;
  }
  return timeN;
}

综合来看,百度对前端的要求其实更看重的是解决问题的能力以及一些很基础的前段知识。面试的过程,其实也是复盘自己的过程,通过一次次的复盘来更加清楚自己的优劣势,明确自己的定位,这样才能在以后的工作中扬长补短,逐渐完善自己的知识体系。

前端学习内容复杂、网上资料良莠不齐,想要靠自己梳理清楚确实不容易,为了帮助想要在这条路上一路走到黑的朋友,我梳理了各个大厂前端工程师常考必考的面试题型,总结出这269页「前端大厂面试宝典(含真题详细解答)」。

HTML

  • html 语义化
  • canvas 相关
  • svg和canvas的区别?
  • html5有哪些新特性?
  • 如何处理HTML5新标签的浏览器兼容问题?
  • 说说 title 和 alt 属性
  • HTML全局属性(global attribute)有哪些

CSS

  • 让一个元素水平垂直居中,到底有多少种方案?
  • 浮动布局的优点?有什么缺点?清除浮动有哪些方式?
  • 使用display:inline-block会产生什么问题?解决方法?
  • 布局题:div垂直居中,左右10px,高度始终为宽度一半
  • 盒模型
  • CSS如何进行品字布局?
  • CSS如何进行圣杯布局
  • CSS如何实现双飞翼布局?
  • 什么是BFC?
  • 触发条件
  • BFC渲染规则
  • 应用场景

JavaScript

  • JS原始数据类型有哪些?引用数据类型有哪些?
  • null是对象吗?为什么?
  • ‘1’.toString()为什么可以调用?
  • 0.1+0.2为什么不等于0.3?
  • 什么是BigInt? 为什么需要BigInt?
  • 如何创建并使用BigInt?
  • typeof 是否能正确判断类型?
  • instanceof能否判断基本数据类型?
  • 能不能手动实现一下instanceof的功能?
  • Object.is和===的区别?
  • [] == ![]结果是什么?为什么?
  • JS中类型转换有哪几种?
  • == 和 ===有什么区别?
  • 对象转原始类型是根据什么流程运行的?
  • 如何让if(a == 1 && a == 2)条件成立?
  • 什么是闭包?
  • 闭包产生的原因?
  • 闭包有哪些表现形式?
  • 如何解决下面的循环输出问题?
  • 原型对象和构造函数有何关系?
  • 能不能描述一下原型链?
  • JS如何实现继承?
  • 函数的arguments为什么不是数组?如何转化成数组?
  • forEach中return有效果吗?如何中断forEach循环?
  • JS判断数组中是否包含某个值
  • JS中flat—数组扁平化
  • 数组中的高阶函数
  • 能不能实现数组map方法 ?
  • 能不能实现数组reduce方法 ?
  • 能不能写一个完整的深拷贝?
  • 数据是如何存储的?
  • V8 引擎如何进行垃圾内存的回收?
  • 描述一下 V8 执行一段JS代码的过程?
  • 宏任务(MacroTask)引入
  • nodejs 和 浏览器关于eventLoop的主要区别
  • nodejs中的异步、非阻塞I/O是如何实现的?
  • JS异步编程有哪些方案?为什么会出现这些方案?
  • 能不能简单实现一下 node 中回调函数的机制?
  • Promise 凭借什么消灭了回调地狱?
  • Promise 如何实现链式调用?
  • 现Promise的 all 和 race
  • 解释一下async/await的运行机制

HTTP

  • HTTP 报文结构是怎样的?
  • HTTP有哪些请求方法?
  • GET 和 POST 有什么区别?
  • 如何理解 URI?
  • 如何理解 HTTP 状态码?
  • 简要概括一下 HTTP 的特点?HTTP 有哪些缺点?
  • 对 Accept 系列字段了解多少?
  • 对于定长和不定长的数据,HTTP 是怎么传输的?
  • HTTP 如何处理大文件的传输?
  • HTTP 中如何处理表单数据的提交?
  • HTTP1.1 如何解决 HTTP 的队头阻塞问题?
  • 对 Cookie 了解多少?
  • 如何理解 HTTP 代理?
  • 如何理解 HTTP 缓存及缓存代理?
  • 为什么产生代理缓存?
  • 源服务器的缓存控制
  • 客户端的缓存控制
  • 什么是跨域?浏览器如何拦截响应?如何解决?

TCP协议

  • 能不能说一说 TCP 和 UDP 的区别?
  • 说说 TCP 三次握手的过程?
  • 为什么是三次而不是两次、四次?
  • 三次握手过程中可以携带数据么?
  • 说说 TCP 四次挥手的过程
  • 为什么是四次挥手而不是三次?
  • 介绍一下 TCP 报文头部的字段
  • 说说 TCP 快速打开的原理(TFO)
  • 说说TCP报文中时间戳的作用?
  • TCP 的超时重传时间是如何计算的?
  • 说一说 TCP 的流量控制
  • 说说 TCP 的拥塞控制?

浏览器

  • 说一说浏览器缓存?
  • 说一说浏览器的本地存储?各自优劣如何?
  • 说一说从输入URL到页面呈现发生了什么?(网络)
  • 谈谈你对重绘和回流的理解
  • 能不能说一说XSS攻击?
  • HTTPS为什么让数据传输更安全?
  • 能不能实现事件的防抖和节流?
  • 能不能实现图片懒加载?

Vue

  • 什么是MVVM?
  • mvvm和mvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?
  • 组件之间的传值?
  • Vue 双向绑定原理
  • 描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?
  • 虚拟 DOM 实现原理
  • Vue 中 key 值的作用?
  • Vue 的生命周期
  • Vue 组件间通信有哪些方式?
  • vue 中怎么重置 data?
  • 组件中写 name 选项有什么作用?
  • vue-router 有哪些钩子函数?
  • route 和 router 的区别是什么?
  • 说一下 Vue 和 React 的认识,做一个简单的对比
  • Vue 的 nextTick 的原理是什么?
  • Vuex 有哪几种属性?

数据结构与算法

  • 链表
    简单的反转链表
    区间反转
    两个一组翻转链表
    K个一组翻转链表
    如何检测链表形成环?
    如何找到环的起点
    合并两个有序链表
    合并 K 个有序链表
    判断回文链表

  • 栈和队列
    有效括号
    多维数组 flatten
    普通的层次遍历
    二叉树的锯齿形层次遍历
    二叉树的右视图
    完全平方数
    单词接龙
    优先队列
    关于堆的说明
    实现一个最大堆
    实现优先队列
    前 K 个高频元素
    合并 K 个排序链表
    什么是双端队列?
    滑动窗口最大值
    栈实现队列
    队列实现栈

  • 二叉树
    前序遍历 / 中序遍历 / 后序遍历
    最大深度 / 最小深度
    对称二叉树
    二叉树的最近公共祖先
    二叉树的直径
    二叉树的所有路径
    二叉树的最大路径和

完整版PDF资料点击此处免费领取。

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

最后送给大家一句话:

“在某个阶段,你之前积累的东西会以某种自己未曾想到过的方式连接起来,最终是这些经历成就了一个人。这种机会是不可预知(而且非常有乐趣)的,但只会留给默默耕耘的人。”

你需要的只是勇敢的迈出第一步,然后不断的优化自己,总结自己,你一定会拿到你属于自己的offer。

posted @ 2021-06-07 16:05  Android程序员吴彦祖  阅读(388)  评论(0编辑  收藏  举报