2022年上海前端面經分享【攜程、位元組跳動】

HackerLeo發表於2023-03-26

前言

背景:一年半經驗前端,今年三月初提了離職,想著趁著金三銀四期間尋覓好的工作機會。不幸的是,三月初全國各地包括上海爆發疫情,直接導致許多公司開始縮招和鎖 HC,金三銀四變成了銅三鐵四。四月份上海疫情越發嚴重,最終導致全城封控,只能在家準備線上面試。(寄!)

疫情開始的階段,整個社會的氛圍都很消極。沒有辦法,只能邊投簡歷,邊準備面試題,邊調整心情。疫情封控期間只能在家閒著,所以利用這段時間,鞏固了一下 JS 基礎,在 Leetcode 上刷了一些演算法題。萬幸的是,在這期間收到了攜程和位元組跳動的面試邀請(感謝萬分)。那麼廢話不多說了,以下是具體的面試過程:

攜程(旅遊研發部)

技術一面

  1. 常見的 React Hooks 有哪些?

    1. useMemo 是怎麼實現效能最佳化的?
    2. useRef 的應用場景?
  2. 該怎麼實現【一套程式碼,多端執行】,說出你的想法?
  3. Taro 實現跨端的底層機制?
  4. 能說說你會怎樣進行前端效能最佳化嗎?
  5. Chrome Devtools 的 Lighthouse 中的 LCP 是什麼意思?該怎麼減少 LCP 時間?

技術二面

  1. 前端效能最佳化方案?
  2. React.memo 和 shouldComponentUpdate 的作用?
  3. ReactDOM.render 的流程?
  4. 演算法題:實現陣列去重(要求最佳時間複雜度)
function unique(arr) {
  const map = new Map();
  for (let i = arr.length - 1; i >= 0; i--) {
    if (map.has(arr[i])) {
      arr.splice(i, 1);
    } else {
      map.set(arr[i], true);
    }
  }
  return arr;
}
  1. 演算法題:實現獲取陣列第二大的數(要求時間複雜度 O(n))
function getSecond(arr) {
  if (arr.length < 2) return null;
  let max = arr[0];
  let second = arr[0];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > max) {
      second = max;
      max = arr[i];
    } else if (arr[i] > second) {
      second = arr[i];
    }
  }
  return second;
}

業務三面

  1. 介紹專案及主要的使用場景。
  2. 做過哪些前端效能最佳化,你認為專案中最主要的效能瓶頸是什麼?
  3. 你做的專案的推進流程是怎麼樣的?你是怎樣進行專案的時間管理和規劃?
  4. 你是如何跟專案經理、後端等同事對接專案的?

位元組跳動(抖音電商)

技術一面

  1. 專案介紹
  2. 你實現了哪些自定義 Hooks?

    1. 實現自定義 Hooks:useLocalStorage
  3. TypeScript 泛型中 extends 關鍵字的作用
  4. CSS position 屬性有哪些值?

    1. relative 和 absolute 相對於誰而言的?
    2. 怎麼實現 Header 固定在網頁頂端?
    3. 使用 fixed 造成內容塌陷怎麼辦?
  5. 實現一個擁有以下功能的 request 函式:

    1. 功能一:支援快取
    2. 功能二:支援非同步(返回 Promise)
    3. 功能三:支援併發請求

技術二面

  1. 有一個列表,然後為列表的每一項新增一個響應事件,你會怎麼做?

    1. 描述一下 DOM 事件流
    2. e.target 是指向哪一個元素?
    3. 怎麼阻止事件冒泡,怎麼阻止事件捕獲?
    4. React 事件機制
  2. 聊一聊使用者登入流程

    1. token 和 cookie + session 有什麼區別?
    2. 聊一聊掃描二維碼,並透過微信登入的流程
  3. 聊一聊虛擬列表實現

    1. 虛擬列表的列表項可以不固定高度嗎?
  4. 手寫 useMyState
const useMyState = (initial) => {
  const [state, setState] = useState(initial);
  const callbackRef = useRef(null);
  const _setState = (_state, callback) => {
    setState(_state);
    callbackRef.current = callback;
  };
  useEffect(() => {
    callbackRef.current(state);
  }, [state]);
  return [state, _setState];
};
  1. this 指向問題
const obj = {
  a: 10,
  add(x) {
    return this.a + x;
  },
  reduce: (x) => this.a - x,
};

console.log(obj.add(2));
console.log(obj.reduce(2));
  1. 實現 sum(1)(2,3)(4,5,6)...()
const sum = (...args) => {
  const result = args.reduce((pre, cur) => pre + cur);
  return (...args) => {
    if (args.length === 0) return result;
    return sum(result, ...args);
  };
};

console.log(sum(1)(2, 3)(4, 5, 6)());

技術三面

  1. 選一個你認為複雜度比較高的專案,描述一下它的難點。
  2. 在 TCP 建立連線後,HTTP 傳輸資料前,這之間發生了什麼?
  3. 我看你文章有些關於 TypeScript 和集合論之間的關係,簡單講述一下。
  4. 聊一聊 React Fiber ,如果讓你實現 Scheduler 你會怎麼實現?
  5. 演算法題:買股票的最佳時機(Leetcode 121
  6. 演算法題:買股票的最佳時機 Ⅱ(Leetcode 122

總結

幾輪面試下來最大的感觸是,面試官會針對你的專案去延伸,進而廣泛地考察你的基礎知識。攜程更加註重效能最佳化方面的考察,在透過三面過後還會有一個綜合測評和英語測評(綜合測評考察基本邏輯不是很難,英語測評過了六級可以免試)。位元組更加側重於一些原理和演算法的考察,不過位元組的演算法題並沒有想想中那麼難,Leetcode 前 200 簡單和中單難度的題準備一下問題應該不大。

最終順利的拿到了攜程的 offer ,位元組則是倒在三面。位元組面試官的反饋說是:【選一個你認為複雜度比較高的專案,描述一下它的難點】這個問題答得太簡單了,需要再加深一下技術深度,挖掘一下專案難點。以上就是此次面經分享的全部內容了,希望對你有所幫助。

本文參與了SegmentFault 思否面試闖關挑戰賽,歡迎正在閱讀的你也加入。

相關文章