囉嗦的話
本人現在大三,就讀於北京師範大學珠海分校的前端小菜雞。受人蠱惑,1月份開始尋找暑期實習,經歷十分坎坷。因為也拿到自己心愛的offer啦,有的公司也已經穩了,等HR面或者等offer啦,所以特來分享一下俺的經歷哈哈哈,希望對大家有所幫助!!
心裡準備
沒有名校光環,沒有大廠實習經歷,沒有ACM金牌,一無所有,唯有堅持、努力、思考可以幫助我們
常見QA
這些俺就沒有研究太多了哈哈哈,就簡單扯一點點噗噗
前端技術學習路徑
我個人的話,是這樣子學的噗噗
graph LR
css-->js
js-->dom
React-->Webpack
Webpack-->Taro
複製程式碼
其實說實話,對於技術棧這些東東我倒也沒有太仔細的去研究過噗噗,大概就是以下這些吧:
- React/Vue
- Webpack
- Babel
- Html5
- Css3
- Typescript
- Sass/Less
- Git
基本都是平時可能做專案會碰到,比較常見的東東
前端框架學習
因為我是大一時候接觸React
的,所以也是情有獨鍾,Vue也只是瞭解一些基本的原理還有使用方法,沒有深入研究。俺覺得如果要研究研究框架的話。就這樣子吧!
- 瞭解框架出現的原因
- 瞭解框架解決了那些問題/難點
- 瞭解框架基本語法、使用方式
- 瞭解框架的編碼規範
- 瞭解框架的坑、以及出現的原因
- 瞭解框架實現的原理
- 瞭解框架的原始碼
- 自己寫一個框架(劃掉
大廠演算法/筆試
這個東東其實我倒也沒有感受的太深,就是我的感受就是,位元組跳動的演算法要求會比別的大廠會高(來自一面掛的小菜雞)
筆試題
因為今年阿里內推沒有筆試,TX也還沒到常規批的筆試,就只經歷過美團、快手的筆試。大家可以去看一下他們的筆試題,反正俺自閉了~
基本就幾個方向吧,大家可以去leetcode
瘋狂刷題打卡!
- 動態規劃
- 圖論
- DFS/BFS
- 貪心演算法
- 排序
- 堆
- 陣列/字串
程式碼評測題/面試中的筆試
大家可以看看阿里跟TX的程式碼評測題,其實他們出題的感覺挺像的。基本流程都差不多
一般分為3 - 4題吧
- 第一題一般是一道leetcode難度easy/medium難度的演算法題,都是比較常見的吧,一般是連結串列/陣列/字串
- 第二、三題一般是結合實際情況的演算法題,今年常見的是DFS的題型,例如模擬
css選擇器
來找節點,或者求載入依賴
的順序。 - 最後一題一般是一個程式碼綜合題,一般做不出來的,時間太短了,像什麼模擬貪吃蛇啊,或者寫一個React元件啊之類的
或者說可能是純實踐的操作題,這些基本都是我面試中遇到過的東東,例如:
- 實現深拷貝
- 實現觀察者模式/訂閱釋出
- 實現下劃線形式轉換大駝峰(a_bb_ccc -> ABbCcc)
- 實現排序
- 實現函式柯里化
- 實現函式扁平化
大廠前端的要求
這個的話,其實我感受不是很明顯,就我而言吧,我覺得他們想要的是,對原理的東西一定要了解/熟悉,有做一定的實踐。例如`:
面試官:
webpack
,babel
有使用過嗎?
面試官:那你自己寫過嗎?
類似這種,不僅要我們瞭解,會使用,還需要知道一些原理,並且自己會加以改進。
無論什麼都是這樣的,再比如像是React
。他們或許不會問你怎麼使用,他們喜歡問:
面試官:
keys
的作用,如果列表元素重新排序,是否會重新渲染
面試官:setState
非同步or同步,平時有遇到過嗎
面試官:React的阻止冒泡怎麼樣的,跟原生有什麼區別
等等之類的東東,就是一些我們平時可能不會在意的小坑,或者需要注意的東西。需要我們不僅會用也要知道為什麼這樣用。
前端複習重點
當然還是基礎優先啦~
- 網路
- 瀏覽器
- css
- js
- 效能
- 框架
等等這些,就我而言,其實我也不知道什麼是重點,但是我覺得前端效能優化方面很多面試官都喜歡問
- 常見的效能優化方式
- 你如何發現效能不好
- 如何發現記憶體洩漏
- 怎麼提高首屏渲染速度
- 如何優化介面訪問
- 如何實現高幀率動畫
- 效能優化的指標
等等這些,關於效能方面的東西,感覺會比較常問
個人建議
前期準備
- 面試最重要還是得基礎紮實hhhh,例如前端相關的知識點,我們可以面經或者書籍來惡補!,基礎一定要紮實,做不到脫口而出也要思考一下吧大致的東東講出來。
- 最重要還是得有自己專案,因為大廠更看重你的實踐能力,以及在實踐中的思考,難點的解決,所以我覺得有一個自己的專案,無論是在簡歷篩選或者是面試之中都很有用
- 做好平時的積累、沉澱。例如可以自己總結一些難點,或者易錯的東東,發表一些部落格文章,在社群中與大家分享一下,這都是不錯的!
- 一定要堅持,萬事開頭難,可能覺得知識點基礎都那麼多了,面試怎麼過嘛?但是付出的努力與回報是成正比的,你現在多努力,以後就會有多感謝自己當初的那份執著
- 梳好頭髮,換好衣服(一位被leader吐槽粉色睡衣的小菜雞路過~)
不要緊張
面試大家都會緊張,這是肯定的,但是千萬別過於緊張。我這人本來就是容易緊張的,所以導致面試的時候,經常緊張得說不出話哈哈哈,特別是剛剛開始,前幾次的面試,哇,還是視訊面試,緊張的說不出話hhh直抖腿
所以俺建議吼~可以起來走一走,喝口水,面試前10分鐘可以看看B站,冷靜冷靜,就當做聊天一樣就可以啦!
體現思考
我們很多人面試的時候,我們或許都會選擇去看一些面經,很多基礎的知識點,的確看面經會更加方便、快捷。但是這也有一個弊端...
那就是不能體現我們的 ”思考過程與能力“
舉個例子
TCP三次握手
面試官:你知道TCP三次握手嗎,你講一下吧~
小菜雞:客戶端傳送syn,服務端接收然後傳送syn + ack包給客戶端,客戶端接收後發一個ack,連線成功
emmm,很好,但是這個簡單的答案,但是會不會有所死板,更像是照著書本,標準答案念出來的
面試官:你知道TCP三次握手嗎,你講一下吧~
小菜雞:客戶端傳送syn,跟伺服器說“我要連線啦”,進入syn_send狀態。
服務端接收然後傳送syn + ack包給客戶端,跟客戶端說“我知道了,我這邊ok了”,進入syn_recv狀態。
客戶端接收後發一個ack,跟服務端說”我要連線咯!“,進入establish狀態,連線成功。
emmm,⑧錯⑧錯,帶有了一點點自己的理解在裡面,但是其實還可以加一點東東,可以再詳細解釋一下為什麼是三次握手,而不是兩次。
面試官:(給你個眼神)
小菜雞:因為三次是為了確定雙方的收發能力:第一次,確定了客戶端的傳送能力。第二次,服務端確定了自己的接受能力。第三次,確定了客戶端的接受能力與服務端的傳送能力。
再比如說,如果我們第一次握手,因為卡住了或者別的原因,導致連線請求沒有傳送出去,那麼客戶端會發起第二次連線請求,然後連線成功,之後斷開。這時候!!這時候!!如果第一次握手的請求不卡了,現在發起了連線,而如果只需要兩次握手,那麼現在客戶端與服務端就連線起來了,但是這時候客戶端並沒有東西要傳送,所以就導致服務端資源被佔用啦。
俺就是舉個例子,hhhh說的對不對俺也不知道噗噗。就大概是這種思路嘛,面試官往往只是為了推敲出候選人是否有足夠的思考能力,與技術潛力來承擔起工作的重任。這樣子可以很好的體現出我們的思考能力哈啊哈。
XSS和CSRF攻防
俺們再舉個例子哈哈哈,比如說現在問xss跟csrf,大噶會怎麼回答呢?
面試官:(開始你的表演)
小菜雞:csrf就是跨站頁面請求來進行攻擊,一般我們新增token來防禦,xss就是跨站指令碼攻擊,一般我們過濾一下script標籤啊這些就ok
我們不妨說多一點,發揮口才!!!
面試官:(開始你的表演)
小菜雞:csrf就是跨站頁面請求來進行攻擊,就比如我們現在登入了一個銀行的網頁,然後我們開啟新的標籤頁,點選了一些攻擊的網頁,這時候因為我們剛剛登入,cookie還沒有過期,我們剛剛點選的網頁就會進行csrf攻擊,利用cookie進行csrf攻擊,錢就沒了啦......
css就是跨站指令碼攻擊,分為XXX類,常見的比如現在有一個評論的元件,使用者輸入評論儲存進資料庫,然後別的使用者訪問的時候可以看到。如果這時候使用者植入惡意的js程式碼評論,我們儲存到資料庫中,那樣別的使用者訪問就會被攻擊啦!我們可以通過過濾尖角號,或者把他轉換成html實體來防禦......
舉舉例子~更加生動!面試官更能理解你的意思!
所以俺建議吼~我們看面經之後,或許可以總結一些例子,或者一些深入的東東,例如“為什麼”,“怎麼來的”這些東東,面試的時候可以發揮口才瘋狂吹!
適當引導
面試過幾輪之後,有了一定的經驗,你就會發現,面試官一般會跟著你說的東西,或者根據你的簡歷來進行提問。所以,其實我們可以適當的引導一下面試官問你熟悉的東東。比如......
面試官:優化效能?
小菜雞:balabala ... 重繪、迴流 ... balbala
面試官:那你說一下重回迴流吧~
小菜雞:(舒服了)
嘿嘿,可以通過一些關鍵詞來引導hhhh
面試官:記憶體洩漏?
小菜雞:記憶體洩漏有xxxx情況,我之前用React做一個專案,裡面有一個監聽滾動條,結果發現切換了頁面還在監聽,結果發現是沒有取消時間監聽,發生了記憶體洩漏,之後我通過xxx方法解決了
其實我們這裡可以引導面試官往幾個方面問
- 你的專案,難點等
- 使用hook的useEffect的return方法來取消事件監聽
- 還有哪些記憶體洩漏的情況,如何解決
- 如何發現記憶體洩漏
所以俺的建議吼,這裡只是舉一個簡單的例子,我們其實可以通過很多種方法,來引導面試官來問我們熟悉的東西,而不是被面試官帶進他自己的節奏,把你問倒hhhh
專案難點
如果有自己的專案,那麼有一個特殊的難點會顯得尤為重要(俺因為沒有,被懟的好慘hhhh)最好呢,是一個網上不能輕易找到的功能或者設計。這樣會凸顯自己~嗯!很強!就決定是你了。
或者是一個系統整體的架構之類的,體現出自己對於產品的理解很深哈哈哈。
再或者,可以針對自己現在的專案,總結出一個功能點計劃,現在沒有不代表未來沒有,也可以表現的出自己也瞭解過相關的知識,知道大體的方向,只不過現在還沒有實施,還在計劃之中,體現自己很有熱情!!
熱情熱情
熱情很重要嗷,這個部分科班非科班,本科還是研究生。無論是誰,熱情總能讓面試官對你有好的印象。無關時間長短,只是自己的心態熱情。對一個功能難點深入探究,對技術原理反覆推敲,為自己的專案作出多大多大的努力。俺覺得都是十分好的東東!
稍加思索
面試的時候,問到不會的東東很正常,但是我個人覺得不要立刻說不會,其實可以稍加思索,然後想一想問題前後的聯絡,然後說一下自己的理解。向面試官請求引導,看看能不能答出來。如果實在不行,也可以跟面試官說,這方面還需要加強,面試結束之後自己再查查資料補一補。學習的精神很重要。
虛心請教
很多人覺得面試官很凶,很有壓力,但其實我們應該是抱著學習的心態去面試的。面試只是查漏補缺的過程。我們面試結束之後,其實可以詢問面試官可否加一下好友之類的。然後可以詢問他一些人生的建議、技術的指導等等。厚著臉皮問,不要擔心被嫌棄就好啦哈哈哈。我就是這樣問一個面試官,才學到了很多東西,專案的難點,或者技術的思考之類的東東。
部分面經
阿里の盒馬X數字農業事業部
初面
初面是聊得最久的一次了,一個多小時了吧,不過初面的面試官真的很讓人感動一直在鼓勵我,“好啊好啊”,“沒關係沒關係”,啊太棒了,給俺這個小菜雞很多信心hhhh
- 輸入url到頁面展示
- 瀏覽器儲存
- 如何實現繼承
- 跨域,常用哪個,解釋一下
- 快取
- 重繪迴流
- 效能優化
- React優勢
- React生命週期
- React最佳實踐
- React新特性
- 如果列表元件要新增一些內容,例如標題,簡介等,你會怎麼對程式碼進行修改(容器元件 -> 展示元件)
- csrf 和 xss
- flex
- 判斷是否為陣列
- typeof arr === 'object'
- 瀏覽器事件迴圈,node事件迴圈
- 事件委託
- webpack流程,外掛
- koa原始碼
- koa洋蔥模型
- mobx原理
- 首屏優化
- async/await Promise
- 盒模型
- babel原理
- Taro原理
一面
一面俺就放放筆試題還有俺自己做的情況吧哈哈哈哈,一面的面試官跟俺說拓撲排序,俺才知道原來還有這種東西(流淚...
筆試題目
- 給定一個連結串列,判斷連結串列中是否有環,比如下圖這種即為有環連結串列。 加分項:使用空間複雜度 O(1) 實現
- 分析一個專案的依賴結構,並按依賴優先順序排序。 已知一個專案的依賴結構,期望在前端通過 loader 的方式非同步載入相關的元件,而我們期望依賴在載入的過程中:
- 每一個依賴被載入後都會被立刻執行,那麼如果要爭取載入一個依賴,則其子依賴都應該優先被載入
- 每一個依賴不希望在錢多出現冗餘的情況,若依賴出現多版本的情況,則預設使用更新的版本,比如已知專案依賴結構為(其中 @ 後面的為依賴版本號):
ProjectA
- a@0.1.0
- d@0.2.0
- c@0.1.0
- b@0.1.1
- e@0.1.2
- c@0.1.2
- c@0.2.0
複製程式碼
則其中一種輸出的依賴優先順序排序為:
['d@0.2.0', 'c@0.2.0', 'a@0.1.0', 'e@0.1.2', 'b@0.1.1']
輸出分析: 為了讓 a 載入後可以爭取執行,則必須先載入 d 和 c,b 的載入同理,又因為在整個依賴關係下,c 的最新版本為 0.2.0 於是有了如上的輸出結果。
- 請用 React 實現一個搜尋框元件,功能包括:
- 輸入文字字數限制
- 可配置輸入文字約束,比如僅限輸入數字
- 使用者輸入時可支援關鍵字搜尋,並出現下拉框展示相關項
俺的答案
- 第一題leetcode原題來的,環形連結串列好像是,可以用快慢指標或者簡單的集合
const cycle1 = function (node) {
let set = new Set()
while (node) {
if (set.has(node))
return true
else
set.add(node)
node = node.next
}
return false
};
const cycle2 = function (node) {
let start = node
let end = node.next
while (start !== end) {
// 沒有環就null
if (end === null || end.next === null) return false
start = start.next
end = end.next.next
}
return true
}
複製程式碼
- 第二題的話我拿到題目第一個想到的就是DFS來尋找那些依賴,然後最後再對依賴這些進行版本比較(其實應該用集合、還有拓撲排序來優化)
這題有大佬在評論區指出錯誤啦!之前那個版本是比較字串,但是忽略了多位數字版本的情況,例如
b@0.2.22
與b@0.2.3
,結果應該是前者,但之前版本是輸出後者,現在修改了一下!好嘞!
function update(npmList) {
let versions = {}
let res = []
// 比較版本號
function cmp(a, b) {
const versionListA = getVersion(a).split('.')
const versionListB = getVersion(b).split('.')
for (let index = 0; index < 3; index++) {
const versionA = parseInt(versionListA[index])
const versionB = parseInt(versionListB[index])
if (versionA > versionB) return a
else if (versionA === versionB) continue
else return b
}
return a
}
// 獲得版本號
function getVersion(str) {
return str.substr(str.indexOf('@') + 1)
}
function dfs(npmList) {
if (npmList.length === 0) return
npmList.forEach((npm) => {
const { name, deps = [] } = npm
// 先遍歷他們的依賴
dfs(deps)
let key = name.substr(0, name.indexOf('@'))
// 如果依賴不存在則新增,若已存在,則取最新版
if (!versions[key]) {
versions[key] = name
} else {
versions[key] = cmp(versions[key], name)
}
// 新增進最後的載入列表
res.push(key)
})
return
}
dfs(npmList)
// 去除重複項,然後將包名轉換為依賴名,eg: a -> a@0.1.0
return [...new Set(res)].map(key => versions[key])
}
複製程式碼
- 第三題的話,我粗略寫了一下噗,寫的也不是很好,用React整的
// 第三題React部分第三題React部分第三題React部分第三題React部分第三題React部分
import React, { Component } from 'react';
import './input.css'
function debounce(fn, delay = 500) {
let timeout = null
return function (e, ...args) {
e.persist && e.persist()
timeout && clearTimeout(timeout)
timeout = setTimeout(() => {
fn.call(this, e, ...args)
}, delay)
}
}
class Tips extends Component {
render() {
const { tipsList } = this.props
return tipsList && tipsList.length !== 0 ? (
<div className="tips__container">
{tipsList.map((item, index) => {
return (
<a href="#" key={index} className="link">{item}</a>
)
})}
</div>
) : <div></div>
}
}
export default class Input extends Component {
constructor(props) {
super(props);
this.state = {
keyWords: [
'前端工程師1', '前端高階開發1', '後端工程師1', '測試開發1', '專案主管1', 'dress', 'Recent', '123456', 'awdad1'
],
inputValue: '',
inputType: 'text',
inputMaxLen: 20,
wordsList: []
}
this.handleInput = debounce(this.handleInput, 200)
this.handleMaxLenChange = debounce(this.handleMaxLenChange, 400)
}
handleInput = (e) => {
const { target: { value } } = e
const { keyWords } = this.state
const tipsList = !value
? []
: keyWords.filter(item => {
const res = item.search(new RegExp(value, 'i'))
return res !== -1
})
this.setState({
inputValue: value,
tipsList
})
}
handleTypeClick = (e) => {
const { target: { name } } = e
this.setState({ inputType: name })
}
handleMaxLenChange = (e) => {
const { target: { value } } = e
const { inputValue } = this.state
const newInputValue = inputValue.substr(0, +value)
// 如果設定最大長度小於現在關鍵詞的長度,則擷取一下
this.input.value = newInputValue
this.setState({ inputMaxLen: value, inputValue: newInputValue })
}
render() {
const { tipsList, inputType, inputMaxLen } = this.state
return (
<div className="container">
<div className="control__container" onClick={this.handleTypeClick}>
<button name="text">文字</button>
<button name="number">數字</button>
<span>最大長度: </span>
<input type="number" placeholder="預設: 20" onInput={this.handleMaxLenChange} />
</div>
<div className="input__container">
<div className="input__wrap">
<input
ref={input => this.input = input}
placeholder="請輸入關鍵詞"
type={inputType}
maxLength={inputMaxLen}
onInput={this.handleInput} />
<button>搜尋</button>
</div>
<Tips tipsList={tipsList} />
</div>
</div>
)
}
}
複製程式碼
// 第三題CSS部分第三題CSS部分第三題CSS部分第三題CSS部分第三題CSS部分第三題CSS部分
.container {
width: 600px;
height: 400px;
margin: 0 auto;
padding: 30px;
background: #fff;
}
.input__container {
margin-top: 30px;
}
.input__wrap {
display: flex;
align-items: center;
}
.input__wrap input {
box-sizing: border-box;
width: 85%;
height: 50px;
padding: 0 10px;
border: #666 1px solid;
border-right: 0;
outline: none;
}
.input__wrap button {
cursor: pointer;
box-sizing: border-box;
width: 15%;
height: 50px;
color: #fff;
font-size: 20px;
border: none;
border: #666 1px solid;
outline: none;
background: #1890ff;
}
.control__container {
display: flex;
align-items: center;
}
.control__container button {
cursor: pointer;
width: 50px;
height: 30px;
margin-right: 10px;
color: #fff;
outline: none;
border: #333 1px solid;
border-radius: 8px;
background: #1890ff;
}
.control__container span {
margin-left: auto;
margin-right: 10px;
color: #666;
font-size: 14px;
}
.tips__container {
overflow-y: scroll;
max-height: 200px;
border: #333 1px solid;
border-top: 0;
}
.tips__container .link {
display: block;
height: 30px;
padding: 5px 10px;
color: #666;
line-height: 30px;
text-decoration: none;
}
.tips__container .link:hover {
color: #fff;
background: #666;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
display: none;
}
複製程式碼
二面
二面主要是結合專案來問的,抓住一個功能發散開來,例如我專案的聊天室的功能,嚇得我好慌好慌hhh,不過面試官人很好一直引導我,特別是那些場景題,引導我去思考,啊,太感動了!!!
- 專案の各種東東
- 聊天私聊怎麼做
- 聊天記錄未讀訊息怎麼做
- 聊天離線資訊處理
- session會話管理如何實現(使用者登入後,開啟新標籤頁輸入url訪問資源)
- 訪問資源許可權控制
- 事件佇列題
- websocket如何連線
- 做題系統元件的設計與擴充(擴充更多型別的題目,如何設計元件)
- 使用者鑑權系統設計
- 為什麼密碼錶跟使用者資訊表分開放
- 資料庫表的設計
三面
這一面也是結合專案來問的。啊,三面的面試官真的太好了,期初我的小專案沒什麼難點(我都以為涼透透了嗚嗚嗚),然後面試官給了提了幾個建議,讓我多去深入思考思考,面試完之後去找他請教問題,也一直很有耐心給我指導指導,啊,太棒了吧?
- 專案の各種東東
- 飛豬為什麼掛了
- 專案難點
- 小程式登入怎麼做的
- 封裝了什麼元件
- 建議:線上閱卷、批註、修改錯別字等(canvas繪製)
- 建議:實時監控每個同學的進度(選擇答案後之後教師端更新/攝像頭監控)
- a與b聊天,將他們的記錄,多選,然後合併發給c,如何設計
- 除了編譯成小程式,有試過app嗎
四面
四面應該是總監面,還是得感謝三面的面試官給我提的建議,之後做出來之後,發現這個東東可以作為專案的一個難點來吹哈哈哈!四面主要還是圍繞專案來問,我個人覺得關注的更是自己的思維、對技術的認識、對自己未來的發展規劃等巨集觀的內容
- 專案難點(canvas繪製公式
- websocket實現,聊天功能的實現(心跳檢測,斷線重連
- 專案の細節
- 聊天資訊的一致性,時序性
- 目標、具體想通過實習學到什麼
- 技術規劃,之後學些什麼
五面
五面是交叉面,心驚膽跳嗚嗚嗚,希望不要掛我...五面問的大多是基礎方面的內容,不過也是結合專案來問的,這一面面試官主要關注的是
效能
方面的內容,例如資料埋點啊、頁面載入時間、介面響應時間等一系列關於效能方面的問題,他希望的是資料量化的一個東東,具體的實現,達成了什麼目標等
- 專案做了那些事情
- 小程式執行池
- 小程式和H5的區別
- 快取存在哪(強快取、協商快取分別通過什麼欄位儲存
- React與Vue的區別
- React的優勢
- Taro編譯的機制
- Taro支援的端有哪些
- node的機制、優勢
- 專案的難點,如何解決,遇到的問題
- 如何監控效能
- 嘗試做了哪些效能上的優化
- 收集使用者資訊?資料埋點?效能指標?量化指標?
- 資源大小,載入速度,頁面渲染時間,介面訪問時間
- 如何優化node後臺的介面(sql優化,表結構重寫
- 使用什麼伺服器,部署在什麼作業系統上
- 多人同時訪問介面測試過嗎?最高承載多少
- webpack如何減小資源打包大小
- 擅長什麼
- 你的優勢是什麼
- 目標?規劃?
騰訊のWXG開放平臺小程式基礎部
一面
一面是筆試 + 面試,俺也放放題目跟俺的答案吧!
筆試題目
- 實現⼀個函式 reverse(a, n) ,反轉⼀個含有 n 個整數的陣列 a(直接在陣列a上操作,元素交換次數 儘可能少,不能使⽤js Array 類內建屬性和⽅法)。
- 實現⼀個函式 countLongest(tree) ,輸⼊⼀棵⼆叉樹,返回⼆叉樹中距離最⻓的兩個葉⼦節點之間 的距離。
var x = [0, 1, 2, 3]
reverse(x, 4) // x = [3, 2, 1, 0]
var y = [1, 2, 3, 4, 1]
reverse(y, 5) // y = [1, 4, 3, 2, 1]
var tree1 = {
value: 1,
left: {
value: 2
},
right: {
value: 3
}
}
countLongest(tree1) // 2
var tree2 = {
value: 1,
left: {
value: 2,
left: {
value: 3,
left: {
value: 6
}
},
right: {
value: 4
}
},
right: {
value: 5
}
}
countLongest(tree2) // 4
複製程式碼
- 在前端開發中,通常會把多個js⽂件合併成⼀個⽂件,以減少⽹絡請求次數,達到優化載入速度的⽬ 的,但是當⽂件之間存在依賴關係時,對js合併的順序,會有⼀定的要求,⽐如 A.js 依賴了 B.js,那打 包後的⽂件,B.js 需要排在 A.js 的前⾯。 實現⼀個函式 resolve(tree) ,根據js的依賴關係樹 tree,輸出合理的打包順序的陣列(結果可能不 唯⼀,輸出其中⼀種即可)。
樣例
var tree1 = {
name: 'main.js',
require: [{
name: 'A.js'
}, {
name: 'B.js'
}]
}
resolve(tree1) // ['A.js', 'B.js', 'main.js']
var tree2 = {
name: 'page.js',
require: [{
name: 'A.js',
require: [{
name: 'B.js',
require: [{
name: 'C.js'
}]
}]
}, {
name: 'D.js',
require: [{
name: 'C.js'
}, {
name: 'E.js'
}]
}]
}
resolve(tree2) // ['C.js', 'E.js', 'D.js', 'B.js', 'A.js', 'page.js']
複製程式碼
- 給定⼀個整數陣列 a,實現⼀個函式 countMax(a) ,計算出從 a 中選擇出多個不相鄰元素組成最⼤的 和是多少。
樣例
var x = [1, 4, 5, 3]
countMax(x) // 7
var y = [3, 12, 6, 2, 4]
countMax(y) // 16
複製程式碼
俺的答案
- 就是簡單的倒置hhh
function reverse(arr) {
let len = arr.length
for (let start = 0; start < Math.floor(len / 2); start++) {
let end = len - start - 1;
[arr[start], arr[end]] = [arr[end], arr[start]]
}
return arr
}
複製程式碼
- 這題是leetcode原題好像,就算算深度
function countLongest(tree) {
if (!tree) return 0
let res = 0
function dfs(node) {
if (!node) return 0
const leftMax = dfs(node.left)
const rightMax = dfs(node.right)
res = Math.max(leftMax + rightMax, res)
return Math.max(leftMax, rightMax) + 1
}
dfs(tree)
return res
}
console.log(countLongest({
value: 1,
left: {
value: 2
},
right: {
value: 3
}
}))
console.log(countLongest({
value: 1,
left: {
value: 2,
left: {
value: 3,
left: {
value: 6
}
},
right: {
value: 4
}
},
right: {
value: 5
}
}))
複製程式碼
- 第三題是不是很眼熟哈哈哈,跟盒馬一面的筆試題好像(其實我發現很多面試筆試題都有這相關的影子)還是DFS來找
function resolve(npmList) {
const res = []
function dfs(npmList) {
if (npmList.length === 0) return
npmList.forEach((npm) => {
const { name, require = [] } = npm
dfs(require)
!res.includes(name) && res.push(name)
})
return
}
dfs(npmList)
return res
}
console.log(resolve([{
name: 'page.js',
require: [{
name: 'A.js',
require: [{
name: 'B.js',
require: [{
name: 'C.js'
}]
}]
}, {
name: 'D.js',
require: [{
name: 'C.js'
}, {
name: 'E.js'
}]
}]
}]))
複製程式碼
- 用動態規劃來找
function countMax(arr) {
const len = arr.length
const dp = new Array(len).fill(0);
dp[0] = arr[0]
dp[1] = arr[1]
dp[2] = arr[0] + arr[2]
for (let i = 3; i < len; i++) {
dp[i] = arr[i] + Math.max(dp[i - 2], dp[i - 3])
}
return Math.max(dp[len - 1], dp[len - 2])
}
console.log(countMax2([1, 4, 5, 3]))
console.log(countMax2([3, 12, 6, 2, 4]))
複製程式碼
面試內容
- 專案
- 為什麼用token不用cookie
- 跨域(前端跟前端的跨域,iframe之間)
- xss
- React與Vue的對比
- Taro與其他多端框架
- 主要還是專案發散
- 如何實現輪播圖
二面
二面基本都是一些基礎吧,但是就有些地方會深入去挖這樣子
- https原理,握手過程(何時對稱/非對稱,誰先誰後,為什麼這樣)
- 常見的優化
- webp格式優化了多少
- 快取以鍵值形式存在瀏覽器,鍵是什麼,值是什麼
- 設計一個快取策略,(hash值)
- React的key
- React與Vue的區別
- Taro與小程式官方框架的區別
- 小程式執行池
- React列表key固定,順序調換會渲染嗎(不會)
- 如何判斷效能瓶頸
- 專案の各種東東
三面
三面感覺還不夠二面難,問的比較常見吧應該說,然後也是問問專案這樣子
- 演算法:判斷陣列中是否存在兩個數相加等於目標值,給出多種思路與時間空間複雜度(暴力迴圈,排序後迴圈剪枝,動態規劃)
- es6的class如何實現私有變數(symbol + 閉包)
- 如何進行效能監控
- 常見的效能優化方法
- 記憶體洩露如何發現,如何解決
- 垃圾回收機制
- 跨域(cors + jsonp + 其他不常見的跨域方法)
- 瀏覽器快取
- 實現深拷貝,深拷貝的用途
- xss、csrf
- cookie與token的工作原理,區別,如何設計
- http1.1、http2.0
- http無狀態
- websocket是什麼協議,如何連線
- websocket有什麼優勢,對比輪訓呢
- 事件迴圈
- setTimeout是否準時,如果不是則應該提前還是延遲
- webpack流程
- 常見的http狀態碼
- babel原理、taro原理
- map中的鍵值會不會被回收(weakMap,weakSet等)
- 專案....難點、設計、收穫
- 平時如何學習
美團到店事業部
一面
- 專案
- 原型鏈
- 繼承
- instanceof
- 事件迴圈
- 非同步任務有哪些,底層如何實現(不會
- websocket
- 輪詢的弊端
- websocket的弊端與優勢
- TCP三次握手
- 為什麼需要三次握手
- 如果兩次握手會發生什麼,保持不必要的連結主要是瀏覽器端還是服務端收到影響大
- TCP的擁塞問題(不會
- xss和crsf
- 跨域(種類,如何使用
- 同源策略
- 跨域為了解決什麼問題
- cookie和token
- 如何使用token,設計
- 意向城市
- 為什麼選擇前端
- 前端學習的規劃
- koa中介軟體模型,洋蔥模型
- 三道演算法
1. 合併兩個有序連結串列
2. 找出陣列第K大的數
3. 晨晨是個愛跑步的孩子,這一天,他準備跑正好k米。
他所在的城市的道路可以看做n個點,m條無向邊組成的圖,
每條邊有一個固定的長度。 晨晨有強迫症,
他跑步前往一個目的地一定要走最短路(當然有多條最短路就可以隨意選擇了)。
晨晨希望知道,他正好跑k米能走到的目的地的個數。
注意,目的地可能在圖中的點和邊上,且該目的地距離晨晨的起點的最短路正好k米。
若k大於所有路徑之和自然不存在這樣的目的地,輸出結果自然為0。
複製程式碼
二面
- function和箭頭函式
- 箭頭函式有什麼特殊的地方
- React的生命週期哪些是不安全的,為什麼
- 為什麼會出現React Hooks
- Memo跟useCallback的區別與聯絡
- hooks模擬生命週期
- 記憶體洩漏
- 如何監控記憶體洩漏,如何發現(全域性變數,閉包,監聽事件,定時器
- SPA的優缺點
- 首屏載入如何優化
- webpack的plugin跟loader的區別
- css垂直居中
- margin相對於誰
- 移動端用什麼佈局
- 如何還原設計稿
- em、rem
- margin-top百分比相對於什麼
- 圖片格式之間的區別
- 如何檢測瀏覽器不支援webp(img onerror
- Promise的reject跟catch,場景,你如何使用
- class 與 function的區別
- class實現靜態變數
- for in 和 Object.keys的區別
- 類繼承的特點
- ES6的Map與物件有什麼區別
- git rebase/stash/commit
- 不用div如何包裹多個元素(Fragment,<><>).
- 原型鏈,作用,如何實現,原理
- 盒模型
- 筆試題:陣列扁平化排序去重
- 筆試題:實現柯里化函式
三面
- 專案成就,經歷,心得(瘋狂追問
- css移動方塊(css3,setInterval,requestAnimationFrame)
- 為什麼requestAnimationFrame能夠做到60幀
- javascript引擎,v8引擎,垃圾回收
- v8引擎跟別的有什麼區別
- 程式碼編譯大致流程
- babel
- http跟https區別,具體
- 如果https發來證照,但是我沒有CA的公鑰怎麼辦(用久的請求CA新的
- 堆跟棧的區別
- 還有別的什麼記憶體塊
- 垃圾回收
- 如何手動垃圾回收(定時器,監聽事件,物件等
- 兩個this指向的問題
- 筆試部分
實現自定義陣列下的排序方法(掛載到陣列原型)
實現下劃線字串轉換大駝峰(asf_ad_ada_adwa -> AsfAdAdaAdawa)
實現釋出訂閱(on,off,emit,once)
複製程式碼