字节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

http://www.tiktok.com/a/b

http://www.tiktok.com

http://www.tiktok.com?a=b

{

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)));
#字节跳动##笔经#
全部评论
赞,很详细,为啥不去了
点赞 回复
分享
发布于 2021-11-11 10:25
老哥准备去哪
点赞 回复
分享
发布于 2021-11-14 18:35
联易融
校招火热招聘中
官网直投
咱两有点像,我也是硕士转cs前端
点赞 回复
分享
发布于 2021-11-23 09:21
老哥还在吗,这个岗位在哪个城市
点赞 回复
分享
发布于 2022-02-17 19:43
const getAddify = (a,b) => {     return new Promise((resolve) => {       asyncAdd(a,b,(err, data) => {         resolve(data)       })     })   }   const sum = async (...params) => {     let res = 0     for(const number of params){       res = await getAddify(res, number)     }     return res   } 这样不可以吗 看你for循环为啥注释了啊
点赞 回复
分享
发布于 2022-02-21 16:49
老哥最后去哪了呀😂
点赞 回复
分享
发布于 2022-02-28 14:21
校友最后去哪里哇,同转码前端,但是比楼主菜多了😂
点赞 回复
分享
发布于 2022-06-20 00:53
这么多手撕题还有算法题吗
点赞 回复
分享
发布于 2022-07-17 23:36

相关推荐

4 38 评论
分享
牛客网
牛客企业服务