字节tiktok前端面经
反正不会去了
一面
判断链表是否有环
function ListNode(val) {
this.val = val;
this.next = null;
}
function isCircle(head) {
if (!head || !head.next || (!(head instanceof ListNode))) return false;
let fast = head;
let slow = head;
while(fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
if (slow === fast) return true;
}
return false;
}
let p0 = new ListNode(0);
let p1 = new ListNode(1);
let p2 = new ListNode(2);
p0.next = p1;
p1.next = p2;
p2.next = p1;
console.log(isCircle(p0)); 异步加法
// 假设有一台本地机器,无法做加减乘除运算(包括位运算)。
// 因此无法执行 a + b、a+ = 1 这样的 JS 代码。
// 然后我们提供一个服务器端的 HTTP API。
// 可以传两个数字类型的参数,响应结果是这两个参数的和。
// 这个 HTTP API 的 JS SDK(在本地机器上运行)的使用方法如下:
// SDK 的模拟实现:
function asyncAdd(a, b, cb) {
setTimeout(() => {
cb(null, a + b);
}, Math.floor(Math.random()*1000))
}
// SDK 模拟调用
asyncAdd(3, 5, (err, result) => {
console.log(result); // 8
});
async function sum(...args) {
if (args.length < 2) return args[0] || 0;
if (args.length === 2) return await asyncAdd(args[0], args[1]);
const len = args.length;
const half = (len >> 1);
const left = await sum(...args.slice(0, half + 1));
const right = await sum(...args.slice(half + 1));
res = asyncAdd(left, right);
// let res = args[0];
// for (let i = 1; i < args.length; i++) {
// res = await asyncAdd(sum, args[i]);
// }
return res;
}
// 现在要求在本地机器上实现一个 sum 函数,支持以下用法:
(async () => {
const result1 = await sum(1, 4, 6, 9, 2, 4);
const result2 = await sum(3, 4, 9, 2, 5, 3, 2, 1, 7);
const result3 = await sum(1, 6, 0, 5);
console.log([result1, result2, result3]); // [26, 36, 12]
})(); 完整解法
function asyncAdd(a, b, cb) {
setTimeout(() => {
cb(null, a + b);
}, Math.floor(Math.random()*100))
}
function sum(...args) {
const result = []
function _sum(resolve, reject) {
new Promise((r, j) => {
let a = args.pop()
let b = args.pop()
a = a !== undefined? a : 0
b = b !== undefined? b : 0 // 如果访问的元素超出了数组范围,则转为 0
asyncAdd(a, b, (err, res) => {
if (err) j(err)
r(res)
})
if (args.length) {
_sum(resolve, reject)
}
})
.then(val => {
result.push(val)
setTimeout(() => {
if (args.length <= 0) {
resolve(sum(...result))
}
}, 100)
})
}
return new Promise((resolve, reject) => {
if (!args || !args.length) resolve(0)
if (args.length == 1) resolve(args[0])
_sum(resolve, reject)
})
}
(async () => {
const result1 = await sum(1, 4, 6, 9, 1, 4)
const result2 = await sum(3, 4, 9, 2, 5, 3, 2, 1, 7)
const result3 = await sum(1, 6, 0, 5)
console.log([result1, result2, result3]) // [25, 36, 12]
})() 二面
以下的结果?
[] == ![]
浏览器的渲染机制
repaint 和 reflow
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
})
promise.then(() => {
console.log(3);
})
console.log(4);class promise {
constructor() {
this.status = 'pending';
}
then(onResvoled, onRejected) {
}
}用 React 实现一个树型结构
{
list: [{
id: '1',
name: 'folder1',
children: [{
id: '11',
name: 'file1'
}, {
id: '12',
name: 'file2'
}]
}, {
id: '2',
name: 'folder2',
children: [{
id: '21',
name: 'folder3',
children: [{
id: '211',
name: 'file3'
}]
}]
}, {
id: '3',
name: "file4"
}]
}
我当场写的
function TreeView(props) {
conste {data, level = 0} = props;
return (data.map(item => {
const level = item.id.length;
return (
<div>
<span>
{'-'.repeat(level)}
</span>
<span>
{item.name}
</span>
{item.children && item.children ? <TreeView data={item.child} level={level + 1}></TreeView> : ''}
</div>
)
}))
} 如果让你来设计一个分页功能,你会怎么设计?前后端如何交互?
HTTP 缓存
TCP/UDP
三面
项目经历
第一道题给我pass了,看我原生js不太行了
实现一个组件,包括 HTML/CSS/JS,点击后出现弹框,需求写弹框,要求可以这么使用,样式尽量的还原设计稿:
function confirm(title, desc) {
// TODO
}
const yes_no = await confirm(
'Do you Want to delete these items',
'Some descriptions');
if(yes_no) {
// the user confirmed.
}
第2题
给定一个由'1'(陆地)和'0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1:
输入:
[
[1,1,1,1,0],
[1,1,0,1,0],
[1,1,0,0,0],
[0,0,0,0,0],
]
输出: 1
示例 2:
输入:
[
[1,1,0,0,0],
[1,1,0,0,0],
[0,0,1,0,0],
[0,0,0,1,1],
]
输出: 3
我用的BFS
function findNumOfIsland(arr) {
const m = arr.length;
if (!m) return 0;
const n = arr[0].length;
if (!n) return 0;
let res = 0;
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (arr[i][j] === 0) continue;
res++;
const queue = [[i, j]];
arr[i][j] = 0;
while (queue.length) {
const [x, y] = queue.shift();
if (x >= 1 && arr[x - 1][y] === 1) {
queue.push([x - 1, y]);
arr[x - 1][y] = 0;
}
if (y >= 1 && arr[x][y - 1] === 1) {
queue.push([x, y - 1]);
arr[x][y - 1] = 0;
}
if (x < m - 1 && arr[x + 1][y] === 1) {
queue.push([x + 1, y]);
arr[x + 1][y] = 0;
}
if (y < n - 1 && arr[x][y + 1] === 1) {
queue.push([x, y + 1]);
arr[x][y + 1] = 0;
}
}
}
}
return res;
}
arr = [
[1,1,0,0,0],
[1,1,0,0,0],
[0,0,1,0,0],
[0,0,0,1,1],
]
console.log(findNumOfIsland(arr)); 第3题
任务
面试官提出的问题将出现在这里。
URL参数解析:
http://www.tiktok.com/a/b?key=1&key=2&key=3&test=4#hehe
{
host: 'www.tiktok.com',
protocol: 'http',
path: '/a/b',
query: {
key: [],
test: '4'
},
hashtag: 'hehe'
}
忘了考虑一些边界情况,面试官也没让我写了
function decode(url) {
let arr = url.split("://");
const protocol = arr[0];
url = arr[1] || '';
arr = url.split('/');
const host = arr.shift();
url = arr.join('/');
arr = url.split('?');
const path = arr.length === 2 ? '/' + arr.shift() : '';
url = arr[0];
arr = url.split('#');
const hash = arr.length === 2 ? arr[1] : '';
const query = {};
arr = arr[0].split('&');
for (let i = 0; i < arr.length; i++) {
const [key, value] = arr[i].split('=');
if (query[key]) {
if (Array.isArray(query[key])) {
query[key].push(value);
} else {
query[key] = [
query[key],
value
]
}
} else {
query[key] = value;
}
}
return {
host,
protocol,
path,
query,
hash
}
}
const url = 'http://www.tiktok.com/a/b?key=1&key=2&key=3&test=4#hehe'
console.log(JSON.stringify(decode(url))); #字节跳动##笔经#
查看17道真题和解析