分享最近看到的面试题

242 阅读1分钟

掘金上的

原文地址:面试:(简单粗暴点)百度一面,直接问痛我

第一题

[1, 2, 3, 4, 5, 6, 7, 8, 9] => [[1, 2, 3],[4, 5, 6],[7, 8, 9]],把一个一维数组变成三个三个的二维数组

我首先想到的是这种

    function getTwoDetpthArrByOne(arr, size) {
      let resultArr = [];
      arr.forEach((item, i) => {
        const pos = (i / size) | 0;

        if (!resultArr[pos]) {
          resultArr[pos] = [];
        }

        resultArr[pos].push(item);
      });
      return resultArr;
    }
    console.log(getTwoDetpthArrByOne([1, 2, 3, 4, 5, 6, 7, 8, 9], 4));

但确实借助 slice 方法写法会更简练

    function convertTo2DArray(arr, chunkSize) {
      var result = [];
      for (var i = 0; i < arr.length; i += chunkSize) {
        result.push(arr.slice(i, i + chunkSize));
      }
      return result;
    }

    var inputArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    var outputArray = convertTo2DArray(inputArray, 3);

    console.log(outputArray);

题目二

第一眼就看到了答案,但我有一种预感,直接让我自己写,怕是没有这么丝滑,还是大一学 C 的时候用过,毕业问的比较多的是冒泡,说起这个快排我也忘了,但是还写文章研究来着...

  //  1 1 2 3 5 8

   function fib(n) {
      if (n == 0 || n == 1) {
        return 1;
      }

      return fib(n - 1) + fib(n - 2);
    }

    console.log(6);

第二种解法就让我眼前一亮了,第一次遇到这个路子,可能是一直觉得多计算一次也没啥吧,毕竟就是个面试题(狗头保命),所谓的性能损耗很难体现出来

但套路基本一样,加变量做辅助,下面是博主的原答案


    function fibonacci(n) {
      if (n <= 1) return n;
      let fib = [0, 1]; // 保存斐波那契数列的结果
      for (let i = 2; i <= n; i++) {
        fib[i] = fib[i - 1] + fib[i - 2]; // 计算第i个斐波那契数
      }
      return fib[n];
    }

    console.log(fibonacci(6));

既然如此,其实没必要把每次的结果都保存

    function fibonacci(n) {
      let one = 1,
        two = 1;
      for (let i = 0; i < n - 2; i++) {
        let temp = two;
        two = one + two;
        one = temp;
      }
      return two;
    }

    console.log(fibonacci(8));

题目三

实现一个 EventBus

    class EventBus {
      constructor() {
        this.eventNames = {};
      }
      on(key, callback) {
        if (!this.eventNames[key]) {
          this.eventNames[key] = [];
        }

        this.eventNames[key].push(callback);
      }
      emit(key, data) {
        if (this.eventNames[key]) {
          this.eventNames[key].forEach((callback) => callback(data));
        }
      }
      off(key, callback) {
        if (this.eventNames[key]) {
          this.eventNames[key] = this.eventNames[key].filter(
            (item) => item !== callback
          );
        }
      }
      once(key, callback) {
        if (!this.eventNames[key]) {
          this.eventNames[key] = [];
        }
        const onceCallback = (data) => {
          callback(data);
          this.off(key, onceCallback);
        };

        this.on(key, onceCallback);
      }
    }

    const emmiter = new EventBus();
    const callback1 = (data) => {
      console.log(data);
    };
    const callback2 = (data) => {
      console.log(data);
    };

    emmiter.on("key1", callback1);
    emmiter.emit("key1", 1);
    emmiter.off("key1", callback1);
    emmiter.emit("key1", 1);

    emmiter.once("key2", callback1);
    emmiter.emit("key2", 16);
    emmiter.emit("key2", 16);

感觉除了once那块有设计的感觉,整体来说实用价值不高

第二篇

面试遇到的

题目一

async function async1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end')
}

async function async2() {
 console.log('async2');
}

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

async1();

new Promise(function(resolve) {
  console.log('promise1');
  resolve();
}).then(function() {
  console.log('promise2');
});

console.log('script end');

输出顺序为:

script start
async1 start
async2
promise1
script end
promise2
setTimeout

首先await async2();后面的代码相当于放在 then 方法里,属于微任务,我实际开发中最常用的场景是等待 ajax 请求的返回,本能的 async2 就 async1 end 了...

这种题就很恶心,有点让人去模拟浏览器执行的感觉,还搞了很多干扰项, 如果真需要这样执行逻辑的代码,顺序还对最后的结果有影响,最后自测的时候,我还是倾向于用浏览器看一下输出顺序来佐证是否与自己预期的一致。

如果考察原理,不如直接一点,搞得向脑筋急转弯一样。