欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

热乎的字节跳动飞书一面二面:

程序员文章站 2024-01-29 14:25:40
...

两面面经放在一起拉,大家加油哦,如果觉得有用的话可以帮我点个赞啦!!!(同时欢迎关注我的微信号: 大明前端)

  1. ES6 语法: 解构赋值,模板字符串,promise,let,const,默认参数…
const obj = {a : 1, b : 2};
const {a, b} = obj; // a = 1; b = 2;
  1. 说一下react和vue在状态更新,组件间通信,DOM渲染的异同,这个要对这两个框架都很熟悉,这个我没答好,给大家推荐一篇文章哈哈哈。
    https://blog.csdn.net/Tokki_/article/details/90726563?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160976102016780299044916%252522%25252C%252522scm%252522%25253A%25252220140713.130102334…%252522%25257D&request_id=160976102016780299044916&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-90726563.first_rank_v2_rank_v29_unweighted&utm_term=react%E5%92%8Cvue%E7%9A%84%E5%8C%BA%E5%88%AB%E5%8F%8A%E4%BC%98%E7%BC%BA%E7%82%B9

  2. 封装一个promise.all;

function all(promises) {
   const values = [];
   return new Promise((resolve, reject) => {
      promises.forEach((promise, index) => {
         promise.then(value => {
            values.push(value);
            if(values.length == promises.length){
               resolve(values);
            }
         }, error => { reject(error) });
      })
   })
}
  1. 手写36进制加法: (这个字节很喜欢考!!!) 我自己之前碰到过一次,现在又碰到了!!!
    function add(a, b) {} // “1” + “1z” = “20”;
    // “1b” + “1” = “1c”;
    下面我给出参考代码:希望各位
function add(a, b) {
   let dictMap = ['0', '1', '2', '3', '4', '5', ......, 'z'];
   let str1 = a.split("").reverse(); // ["z", "1"]
   let str2 = b.split("").reverse();// ["1"]
   let aLen = a.length, bLen = b.length, len = (aLen > bLen ? aLen : bLen) + 1;
   let sum = new Array(len).fill(0);
   for(let i = 0; i < aLen; i++) {
      sum[i] = dictMap.indexof(str1[i]);// [0, 0, 0] => [35, 1, 0];
   }
   for(let j = 0; j < bLen; j++) { // [1]
      sum[j] += dictMap.indexof(str2[i]);// => [36, 1, 0];
   }
   // 进位
   for(let i = 0; i < sum.length-1; i++) {
      if(sum[i] > 35) { 
         sum[i] %= 36;
         sum[i+1] += (sum[i] / 36); // [0, 2, 0];
      }
   }
   // 反向添加
   let builder = "";
   for(let i = len - 1; i >= 0; i--) {
      builder += (dictMap[sum[i]);
   }
   // 以0开头要特判
   if(builder.chat(0) == "0"){
      builder = builder.substring(1);
   }
   return builder;
}
  1. 封装一个EventEmitter类,包括on,emit,off,once.
class EventEmitter {
        constructor() {
            this.handles = {};
        }

        on(evName, callback){
            this.handles[evName] = this.handles[evName] || [];
            this.handles[evName].push(callback);
            return this;
        }

        off(evName, callback){
            let callbacks = this.handles[evName];
            if (callbacks) {]
                this.handles[evName = callbacks && callbacks.filter(fn => fn !== callback);
            }
            return this;
        }

        trigger(evName, ...args) {
            let callbacks = this.handles[evName];
            if (callbacks) {
                callbacks.forEach(callback => {
                    callback.call(this, ...args);
                })
            }
        }

        once(evName, callback) {
            let wrapFunc = (...args) => {
                callback.call(this, ...args);
                this.off(evName, wrapFunc);
            }
            this.on(evName, wrapFunc);
        }
    }
  1. 手写一个节流函数: throttle
function throttle(fn, delay) {
   let timer = null;
   return function(){
      let context = this;
      let args = argument;
      if(!timer){
         setTimeout(() => {
           fn.apply(context, args);
           timer = null;
         }, delay);
      }
   }
}
  1. 说一下三栏布局(左定右定中间自适应): 两种方式( flex + (定位+浮动) ) 比较基础。
    html搭建结构
<div class="container">
   <div class="middle"><h2>中间自适应</h2></div>
   <div class="left"><h2>左边栏</h2></div>
   <div class="right"><h2>右边栏</h2></div>
</div>
.container { 
    height:200px;
    overflow:hidden;
    padding: 0 200px;
 }
.middle {
    width: 100%;
    height: 200px; 
    background-color: deeppink;
    float:left;
 }
.left { 
    width: 200px;
    height: 200px;
    background-color: blue;
    float:left;
    /* 让左边的盒子上去 需要设置其左边距为负的中间盒子的宽度 */
    margin-left: -100%;
    position: relative;
    left: -200px;
 }
.right { 
    width: 200px;
    height: 200px;
    background-color: darkorchid;
    float:left;
    /* 让右边的盒子上去 需要设置其左边距为负的自己的宽度 */
    margin-left: -200px;
    position: relative;
    right: -200px;
 }
  1. 手写一个算法题:给定一个包含非负整数的m * n网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和最小。
    (简单的动态规划,代码就不贴了)。
// 状态转移方程:
// dp[i][j] = nums[i][j] + Math.min(dp[i-1][j], dp[i][j-1])
  1. js如何构建二叉树:
    参考链接: https://blog.csdn.net/zhenzuo_x/article/details/87968492;
  2. 给定一个URL数组,请问js如何实现串行执行[url1, url2, url3,…]
    串行本质上是一个接着一个执行,应该是构建一个promise数组
       const promise1 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(5)
                },200)
        })
       const promise2 = new Promise((resolve, reject) => {
                 setTimeout(() => {
                    resolve(1)
                },300)
        })
     
        const promise3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(7)
                },100)
        })
        var arr=[promise1,promise2,promise3];
    // 第一种方法: async函数
       var fn=async function(arr){
            for(let i=0,len=arr.length;i<len;i++){
                var result=await arr[i]
                console.log(result)
            }
         }   
       fn(arr)
    // Generator
    // 这个递归设计的很巧妙
            const Cgenerator = function (arr) {
            const fn = function* () {
                for (let i = 0, len = arr.length; i < len; i++) {
                    yield arr[i]
                }
            }
            const gen = fn();

            const step = function (nextF) {
                let next=nextF()
                if (next.done) {
                    return;
                }
                if (next.value) {
                    next.value.then((data) => {
                        console.log(data)
                        step(() => { return gen.next(); })
                    })
                }
            }
            step(() => { return gen.next(); })
        }
        Cgenerator(arr)
 // Promise.resolve
 // 这个链式调用设计的也相当巧妙: 前一个promsie执行完毕后返回promise赋值给res
        const promiseThen=function(arr){
            let res=Promise.resolve()
            arr.forEach(item => {
                res=res.then(()=>{
                    return item    
                }).then((data)=>{
                    console.log(data)
                })
            });
        }
        promiseThen(arr)


参考文献:
https://blog.csdn.net/qq_39816673/article/details/94209106?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160976378116780263018323%252522%25252C%252522scm%252522%25253A%25252220140713.130102334…%252522%25257D&request_id=160976378116780263018323&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-3-94209106.first_rank_v2_rank_v29_unweighted&utm_term=promise%E4%B8%B2%E8%A1%8C%E6%89%A7%E8%A1%8C