Skip to content
目录

手撕题目

Object.create()

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

instanceof

js
function myInstanceof(obj, obj2) {
  let proto = Object.getPrototypeOf(obj);
  const prototype = obj2.prototype;
  while (proto) {
    if (proto === prototype) {
      return true;
    }
    proto = Object.getPrototypeOf(proto);
  }
  return false;
}
1
2
3
4
5
6
7
8
9
10
11

new

js
function myNew(fn, ...args) {
  const ans = Object.assign(fn);
  const value = fn.apply(ans, args);
  return value instanceof Object ? value : ans;
}
1
2
3
4
5

debounce(fn, delay)

js
function debounce(fn, delay) {
  let timer = null;
  return function (...args) {
    timer && clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}
1
2
3
4
5
6
7
8
9

throttle(fn, delay)

js
function throttle(fn, delay) {
  let timer = 0;
  return function (...args) {
    let newTimer = +new Date();
    if (newTimer - timer >= delay) {
      fn.apply(this, args);
      timer = +new Date();
    }
  };
}
1
2
3
4
5
6
7
8
9
10

Function.prototype.call

js
Function.prototype.myCall = function (context, ...args) {
  if (typeof this !== "function") {
    throw new Error("type error");
  }
  context ||= window;
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};
1
2
3
4
5
6
7
8
9
10

Function.prototype.apply

js
Function.prototype.myApply = function (context, args) {
  if (typeof this !== "function") {
    throw new Error("type error");
  }
  context ||= window;
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};
1
2
3
4
5
6
7
8
9
10

Function.prototype.bind

js
Function.prototype.myBind = function (context) {
  if (typeof this !== "function") {
    throw new Error("type error");
  }
  const self = this;
  return function () {
    return self.apply(context, arguments);
  };
};
1
2
3
4
5
6
7
8
9

curry(fn)

js
function curry(fn) {
  const judge = (...args) =>
    args.length >= fn.length
      ? fn(...args)
      : (...args2) => judge(...args, ...args2);
  return judge;
}
1
2
3
4
5
6
7

deepClone(obj)

js
function deepClone(obj) {
  if (Array.isArray(obj)) {
    return obj.map((item) => deepClone(item));
  } else if (obj instanceof Object) {
    return Object.fromEntries(
      Object.entries(obj).map(([key, value]) => [key, deepClone(value)])
    );
  } else {
    return obj;
  }
}
1
2
3
4
5
6
7
8
9
10
11

洗牌算法

js
function outOfOrder(arr) {
  arr.forEach((_, index, array) => {
    const randomIndex = ~~(Math.random() * (array.length - 1 - index)) + index;
    [array[index], array[randomIndex]] = [array[randomIndex], array[index]];
  });
  return arr;
}
1
2
3
4
5
6
7

flat(arr)

js
function flat(arr, depth) {
  if (!Array.isArray(arr) || depth <= 0) {
    return arr;
  }
  return arr.reduce((prev, cur) => {
    if (Array.isArray(cur)) {
      return prev.concat(flat(cur, depth - 1));
    } else {
      return prev.concat(cur);
    }
  }, []);
}
1
2
3
4
5
6
7
8
9
10
11
12

Array.prototype.push

js
Array.prototype.push = function () {
  for (let i = 0; i < arguments.length; i++) {
    this[this.length] = arguments[i];
  }
  return this.length;
};
1
2
3
4
5
6

Array.prototype.filter

js
Array.prototype.filter = function (callback) {
  const res = [];
  for (let i = 0; i < this.length; i++) {
    callback(this[i]) && res.push(this[i]);
  }
  return res;
};
1
2
3
4
5
6
7

Array.prototype.map

js
Array.prototype.map = function (callback) {
  const res = [];
  for (let i = 0; i < this.length; i++) {
    res.push(callback(this[i]));
  }
  return res;
};
1
2
3
4
5
6
7

发布订阅模式

js
class EventCenter {
  handlers = {};

  addEventListener(type, handler) {
    if (!handlers[type]) {
      handlers[type] = [];
    }
    this.handlers[type].push(handler);
  }

  dispatch(type, params) {
    if (!this.handlers[type]) {
      return new Error("事件未注册");
    }
    this.handlers[type].forEach((handle) => handle(...params));
  }

  removeEventListener(type, handler) {
    if (!this.handlers[type]) {
      return new Error("事件未注册");
    }
    if (!handler) {
      delete this.handlers[type];
    }
    const index = this.handlers[type].indexOf(handler);
    if (index === -1) {
      return new Error("无该绑定事件");
    } else {
      this.handlers[type].splice(index, 1);
      if (!this.handlers[type].length) {
        delete this.handlers[type];
      }
    }
  }
}
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
32
33
34
35

Object.defineProperty()数据劫持

js
const obj = {
    name: "luowei",
    age: 20,
};
const p = {};
Object.defineProperty(p, key, {
    get() {
        return obj[key];
    },
    set(val) {
        obj[key] = val;
    },
});
1
2
3
4
5
6
7
8
9
10
11
12
13

Proxy数据劫持

js
const obj = {
    name: "luowei",
    age: 20,
};
const proxy = new Proxy(obj, {
    get(target, propName) {
        return Reflect.get(target, propName);
    },
    set(target, propName, value) {
        Reflect.set(target, propName, value);
    },
    deleteProperty(target, propName) {
        return Reflect.deleteProperty(target, propName);
    },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

路由

js
class Route {
  constructor() {
    this.routes = {};
    this.currentHash = "";
    this.freshRoute = this.freshRoute.bind(this);
    window.addEventListener("load", this.freshRoute);
    window.addEventListener("hashchange", this.freshRoute);
  }

  storeRoute(path, callback) {
    this.routes[path] = callback || function () {};
  }
  freshRoute() {
    this.currentHash = location.hash.slice(1) || "";
    this.routes[this.currentHash]();
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

setTimeout与setInterval

js
function mySetInterval(callback, delay) {
  const timer = {
    flag: true,
  };
  function interval() {
    if (timer.flag) {
      callback();
      setTimeout(interval, delay);
    }
  }
  setTimeout(interval, delay);
  return timer;
}

// setInterval实现setTimeout
function mySetTimeout(callback, delay) {
  const timer = setInterval(() => {
    clearInterval(timer);
    callback();
  }, delay);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

JSONP

js
function addScript(src) {
  const script = document.createElement("script");
  script.src = src;
  script.type = "text/javascript";
  document.body.appendChild(script);
}
1
2
3
4
5
6

数组去重

js
const arr = [1, 2, 3, 1, 2, 3];
[...new Set(arr)];
arr.filter((item) => arr.indexOf(item) === index);
// 双for就不说了
1
2
3
4

对象转树

ts
class TreeNodeObj {
  value: number;
  children?: TreeNodeObj[];
}

class TreeNode {
  constructor(
    public value: number,
    public next: TreeNode | null = null,
    public child: TreeNode | null = null
  ) {}
}

const obj: TreeNodeObj = {
  value: 1,
  children: [
    { value: 2 },
    { value: 3, children: [{ value: 5 }, { value: 6 }] },
  ],
};

/**
 * 传入一个obj对象,返回TreeNode
 * @param obj
 */
function objToTree(obj: TreeNodeObj): TreeNode {
  const root = new TreeNode(obj.value);
  if (obj.children) {
    root.child = obj.children.reduceRight<TreeNode | null>((prev, child) => {
      const currentNode = objToTree(child);
      currentNode.next = prev;
      return currentNode;
    }, null);
  }
  return root;
}

console.log(objToTree(obj));
// TreeNode { value: 1,
//   next: null,
//   child:
//    TreeNode { value: 2,
//      next:
//       TreeNode { value: 3,
//         next: null,
//         child:
//          TreeNode { value: 5,
//            next: TreeNode { value: 6, next: null, child: null },
//            child: null } },
//      child: null } }
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

(@type)chunk

ts
type GetSubArrFromArr<
  Arr extends unknown[],
  Length extends number,
  TempArr extends unknown[] = []
> = Arr extends [infer First, ...infer Rest]
  ? TempArr["length"] extends Length
    ? TempArr
    : GetSubArrFromArr<Rest, Length, [...TempArr, First]>
  : TempArr;

type EmptyArrayMerge<T extends unknown[]> = T["length"] extends 0 ? T : [T];

type Chunk<
  Arr extends unknown[],
  Length extends number,
  SubArr extends unknown[] = GetSubArrFromArr<Arr, Length>
> = Arr extends [...SubArr, ...infer Rest]
  ? SubArr["length"] extends Length
    ? [SubArr, ...Chunk<Rest, Length>]
    : EmptyArrayMerge<SubArr>
  : never;

type test1 = Chunk<[1, 2, 3, 4, 5], 3>;
// type test1 = [[1, 2, 3], [4, 5]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Released under the MIT License.