Appearance
手撕题目
Object.create()
js
function create(obj) {
function F() {}
F.prototype = obj;
return new F();
}
1
2
3
4
5
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24