百度前端面試題分享,帶答案

這是我參與更文挑戰的第7天,活動詳情查看:更文挑戰css

碼字不易,您的贊是我持續更新創做的動力。html

在此次找工做的過程當中,百度總體的流程仍是比較規範的,雖然由於第一次去百度大廈的時候被HR告知一面面試官由於會議緣由要臨時取消面試,改約其餘時間。可是以後來到和全部的面試官聊天的過程當中,仍是感覺到了大廠範兒。前端

相較於其餘公司喜歡問原理、問機制,百度的幾面中更關注的是你在工做中是如何運用你所掌握的框架知識的,工做中是如何平衡業務和技術的,會經過一些工做中很實際的問題來一層層的深刻討論,這點我以爲很是好。webpack

下面主要看一下百度線下測試題部分,看看百度更關注一個前端的基本素養是什麼。web

樣式相關

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 ⽚段, 對應如下的哪⼀個渲染效果?
  • 請簡要分析⼀下你的推導思路?
    • 提示, 這個⼩問是必答的, 咱們須要參考你的實際推導依據

img img img img

做答

選B。面試

⾸先,針對 root ⾼度,因爲 root 下的元素只有 div-a 是 relative ,在⽂檔流中;⼜由於全部 div 的盒模型是使⽤的標準盒模型,因此 root 的⾼度就等於 div-a 的⾼度 200px + 其上下邊框的⾼度 3px*2 = 206px ;ajax

而後, 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;
}
複製代碼

綜合來看,百度對前端的要求其實更看重的是解決問題的能力以及一些很基礎的前段知識。面試的過程,其實也是覆盤本身的過程,經過一次次的覆盤來更加清楚本身的優劣勢,明確本身的定位,這樣才能在之後的工做中揚長補短,逐漸完善本身的知識體系。

相關文章
相關標籤/搜索