位元組跳動前端面試經驗
一面面試經驗
1、資料庫正規化
2、TCP & UDP
3、UDP的例子(郵件、直播)
4、Hybrid Uni-App如何引用本地頁面hybrid
5、Webview 巢狀 Webview的原理
6、Webview 通訊 postMessage和postMessage chrome
7、JSBridge的原理
8、前端路由實現 hash模式、histroy模式
9、SEO最佳化有哪些操作;在商品很多的情況下,如何在商品詳情中寫入商品資訊(SSR、服務端渲染在標籤中寫入)
10、效能最佳化中,CSS壓縮的原理、圖片壓縮的原理
11、Webpack中,loader和plugin的原理,傳入物件是什麼
12、Webpack中,TS檔案如何轉成JS檔案
13、瀏覽器的eventLoop和node的eventLoop的區別?Node有哪些微執行緒
14、怎麼實現跨域?JSONP的原理
15、專案部署中,如何解決跨域?
16、多語言翻譯如何實現?
17、演算法題:二叉樹所有根到葉子路徑組成的數字之和
const root = {
value: 1,
left: {
value: 2,
left: {
value: 4,
},
right: {
value: 5,
}
},
right: {
value: 3
}
}
function pathSum(root) {
const paths = [];
/*
* dfs的方式進行遍歷樹
* curr表示當前節點
* path表示已經累計的路徑內容
*/
const dfs = (curr, path) => {
path += curr。value + ‘’; // 路徑累計,需要轉成字串
if(curr !== undefined && curr。left === undefined && curr。right === undefined) {
paths。push(path);
return;
}
if (curr。left !== undefined) {
dfs(curr。left, path);
}
if (curr。right !== undefined) {
dfs(curr。right, path);
}
}
dfs(root, ‘’);
let sum = 0;
for(let i = 0; i < paths。length; i++) {
sum += Number(paths[i]);
}
return sum
}
pathSum(root);
二面面試經驗
程式設計題1:
// 順序執行下面程式碼,請寫出列印結果:
function Foo(){
this。getName = function(){
console。log(‘1’)
};
return this;
}
Foo。getName = function() {
console。log(‘2’);
};
Foo。prototype。getName=function(){
console。log(‘3’);
};
var getName=function(){
console。log(‘4’)
};
function getName(){
console。log(‘5’);
};
// 列印
Foo。getName();// -> 2
getName(); // 函式變數提升 輸出 4
Foo()。getName();// -> 1
getName();// -> 1
new (Foo。getName)();// -> 2
(new Foo())。getName();// -> 1
程式設計題2:
實現 mergePromise 函式,把傳進去的陣列順序先後執行,並且把返回的資料先後放到陣列 data 中
const timeout = ms =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, ms)
})
const ajax1 = () =>
timeout(2000)。then(() => {
console。log(‘1’)
return 1
})
const ajax2 = () =>
timeout(1000)。then(() => {
console。log(‘2’)
return 2
})
const ajax3 = () =>
timeout(2000)。then(() => {
console。log(‘3’)
return 3
})
const mergePromise = ajaxArray => {
// 在這裡實現你的程式碼
let data = [];
// 這裡需要最佳化成,題目給出3個,需要做成list的形式
return new Promise((resolve, reject) => {
ajaxArray[0]()。then((res) => {
data。push(res)
return ajaxArray[1]()
})。then((res) => {
data。push(res)
return ajaxArray[2]()
})。then((res) => {
data。push(res);
resolve(data);
})。catch(err => {
reject(err)
})
})
}
mergePromise([ajax1, ajax2, ajax3])。then(data => {
console。log(‘done’)
console。log(data) // data 為 [1, 2, 3]
})
// 分別輸出
// 1
// 2
// 3
// done
// [1, 2, 3]
程式設計題3:
寫一個定時器函式 myTimer(fn, a, b),每次間隔 a,a+b,a+2b,。。。,a+nb 的時間執行fn,
該定時器返回一個函式為 myClear,可以停止上面的定時器 myTimer(請使用setTimeout來實現該題目,
myTimer函式只調用一次)
let fn = function() {
console。log(‘fn’)
}
let a = 1000, b = 1000;
function myTimer(fn, a, b) {
let timer;
let count = 0;
let delay = a + count * b;
console。log(fn, a, b);
// 這裡使用遞迴進行實現
const repeatSetTimeout = () => {
timer = setTimeout(() => {
fn();
count++;
delay = a + count * b;
repeatSetTimeout();
}, delay);
};
// 首次觸發
repeatSetTimeout();
const myClear = () => {
clearTimeout(timer)
};
return myClear;
}
console。log(fn, a, b);
myTimer(fn, a, b);
問答題:
1、瀏覽器協商快取和強快取的區別?last-modifide 和 ETag的優先順序哪個高?-> Etag高
2、命中協商快取,瀏覽器返回的狀態碼是多少?304
3、HTTP協議頭Cache-Control取值no-cache和no-storage的區別?
no-storage:徹底禁用緩衝,所有內容都不會被快取到快取或臨時檔案中。
no-cache:在瀏覽器使用快取前,會往返對比ETag,如果ETag沒變,返回304,則使用快取。
4、es5的繼承和es6的繼承的區別?哪一個是先生成子類,再生成父類,哪一個想先生成父類,再生成子類
5、http1。0和http2。0的區別,http2。0有哪些提升的地方?
6、Vue使用過程中,為啥需要繫結key?-> 提高diff的效率
三面
1、聊實際專案
2、最有收穫、最有意義的事情是什麼?
3、程式設計題:刪除一個已排序(升序)的單向連結串列中的重複元素,一旦元素重複,刪除全部該重複元素,例如1->2->2->3,
刪除結果為1-3,返回修正後的表頭,參考leetcode原題82。刪除排序連結串列中的重複元素 II https://leetcode-cn。com/problems/remove-duplicates-from-sorted-list-ii/
如果你是普通使用者,在海外網站上發帖,但是網站只告訴你該發帖含有違禁詞,沒有提示具體的違禁詞,你要怎麼找出違禁詞?——二分法查詢,先分成兩部分,然後各自發帖,如果發帖結果為含有違禁詞,繼續二分查詢,直到查詢到該詞