【面试题】手写代码

手写 compose 组件

1
2
3
4
5
6
7
export default function compose(...func: Function[]) {
  return function c(arg: any) {
    func.reduceRight((prev, current, index) => {
      return current.call(null, prev);
    }, arg);
  };
}

手写 deepClone

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function deepClone(obj: any): any {
  let stack = new WeakMap();
  const dp = (obj: any): any => {
    let newObj: any = {};
    if (stack.has(obj)) {
      return stack.get(obj);
    }
    stack.set(obj, obj);

    for (let k in obj) {
      let type = Object.prototype.toString.call(obj[k]);
      switch (type) {
        case "[Object object]":
          newObj[k] = dp(obj[k]);
          break;
        case "[Object array]":
          newObj[k] = obj[k].slice();
          break;
        default:
          newObj[k] = obj[k];
          break;
      }
    }
    return newObj;
  };
  return dp(obj);
}

手写 Array.map

1
array.map(function(currentValue,index,arr), thisValue)
1
2
3
4
5
6
7
Array.prototype.newMap = function (fn, context) {
  let arr = [];
  for (let i = 0; i < this.length; i++) {
    arr.push(fn.call(context, this[i], i, this));
  }
  return arr;
};

手动实现一个 Promisefy 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default function promisify(fn: Function) {
  return function (...args: any[]) {
    return new Promise((resolve, reject) => {
      try {
        let cb = (...res: any[]) => {
          resolve(res);
        };
        fn.apply(null, [...args, cb]);
      } catch (e) {
        console.info("rejected");
        reject(e);
      }
    });
  };
}

实现 Array.reduce

1
2
3
4
5
6
7
8
9
10
11
12
Array.prototype.newReduce = function (fn: Function, prev?: any) {
  for (let i = 0; i < this.length; i++) {
    if (typeof prev === "undefined") {
      prev = fn(this[i], this[i + 1], i + 1, this);
      i++;
    } else {
      console.info("prev", prev);
      prev = fn(prev, this[i], i, this);
    }
  }
  return prev;
};

防抖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
export default function debounce(
  fn: Function,
  params: {
    wait?: number;
    immediately?: boolean;
  }
) {
  let config = Object.assign(
    {
      wait: 1000,
      immediately: false,
    },
    params
  );

  let t: any = null;
  let first: boolean = true;

  return function (...args: any) {
    let context = this;
    if (config.immediately && first) {
      console.info("123123", first);
      fn.apply(context, args);
      first = false;
    }
    t && clearTimeout(t);
    t = setTimeout(() => {
      fn.apply(context, args);
    }, config.wait);
  };
}

截流

1
2
3
4
5
6
7
8
9
10
11
12
export default function throttle(fn: Function, wait: number) {
  let prev = 0;

  return function (...args: any) {
    const context = this;
    let now = Date.now();
    if (now - prev > wait) {
      fn.apply(context, args);
      prev = now;
    }
  };
}

数组拍平

1
2
3
4
5
export default function flat(arr: any[]): any[] {
  return arr.reduce((prev, cur) => {
    return prev.concat(Array.isArray(cur) ? flat(cur) : cur);
  }, []);
}

使用 JS 实现一个 repeat 方法

1
2
3
4
5
6
// 使用 JS 实现一个 repeat 方法
function repeat(func, times, wait) {
  // Todo
}
const repeatFunc = repeat(alert, 4, 3000);
// 调用这个 repeatedFunc("hellworld"),会alert 4 次 helloworld, 每次间隔 3 秒

答案:

1
2
3
4
5
6
7
8
9
10
export default function repeat(func, times, wait) {
  return (str: any) => {
    let count = 0;
    let t = setInterval(() => {
      if (count < times) clearInterval(t);
      func.apply(null, [str]);
      count++;
    }, wait);
  };
}

实现一个 new 方法

1
2
3
4
5
function testNew(Parent, ...rest) {
  let child = Object.create(Parent.prototype);
  let result = Parent.apply(child, rest);
  return typeof result === "object" ? result : child;
}

实现 Object.create

1
2
3
4
5
function create(o) {
  let F = function () {};
  F.prototype = o;
  return new F();
}

实现一个 JS 的 sleep

1
2
3
4
5
function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

JavaScript 实现数组乱序

1
2
3
export default function shuffle(arr: any[]): any[] {
  return arr.sort((a, b) => (Math.random() > 0.5 ? a - b : b - a));
}

实现大数字的相加操作

输入一个任意的四则运算字符串,给出计算结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
export default function exex(strInput: string): number {
  let exec = strInput.match(/(^\d+)|([+*/-])|(\d+$)/g);
  let res = 0;
  if (exec?.length !== 3) return res;
  let numLeft = Number(exec[0]);
  let numRight = Number(exec[2]);

  switch (exec[1]) {
    case "+":
      res = numLeft + numRight;
      break;
    case "-":
      res = numLeft - numRight;
      break;
    case "*":
      res = numLeft * numRight;
      break;
    case "/":
      res = numLeft / numRight;
      break;
    default:
      return res;
  }
  return res;
}

写一个正则匹配出图片的后缀(要求写明字符串匹配的 API)

1
2
3
var str =
  "https://sf3-ttcdn-tos.pa***.com/img/edux-data/xxxxxxxxxxxxxxxxxxx~0x0.jpg";
// todo

写一个函数返回当前节点是其父元素的第几个节点

1
2
3
4
5
function getNodeIndex(node) {
  let index = 0;
  // todo
  return index;
}
✏️ 如有问题,欢迎指正
上一篇 : 【面试题】算法下一篇 : 【面试题】设计模式