深拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function deepClone<T extends Array<T> | any>(obj: T): T {
if (typeof obj !== "object" || obj === null) {
return obj;
}
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);

const result: T = new obj.constructor();

for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}

Promise

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
const PROMISE_STATUS_PENDING = "pending";
const PROMISE_STATUS_FULFILLED = "fulfilled";
const PROMISE_STATUS_REJECTED = "rejected";

class MyPromise {
constructor(executor) {
this.status = PROMISE_STATUS_PENDING; // 记录promise状态
this.value = undefined; // resolve返回值
this.reason = undefined; // reject返回值
this.onResolvedCallbacks = []; // 存放成功回调
this.onRejectedCallbacks = []; // 存放失败回调

const resolve = value => {
if (this.status === PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_FULFILLED) return;
this.status = PROMISE_STATUS_FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(fn => {
fn(this.value)
});
});
}
};

const reject = value => {
if (this.status === PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_REJECTED) return;
this.status = PROMISE_STATUS_REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => {
fn(this.reason)
});
});
}
};

try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}

static resolve(value) {
return new MyPromise(resolve => resolve(value));
}

static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
/**
* 解决链式调用写法
*/
then(onFulfilled, onRejected) {
onFulfilled = onFulfilled || (value => { return value; });
onRejected = onRejected || (err => { throw err; });

return new myPromise((resolve, reject) => {
if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject);
}
if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
execFunctionWithCatchError(onRejected, this.reason, resolve, reject);
}

if (this.status === PROMISE_STATUS_PENDING) {
if (onFulfilled) {
this.onFulfilledFns.push(() => {
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject);
});
}
if (onRejected) {
this.onRejectedFns.push(() => {
execFunctionWithCatchError(onRejected, this.reason, resolve, reject);
});
}
}
})
}

catch(onRejected) {
return this.then(undefined, onRejected);
}

finally(onFinally) {
this.then(() => {
onFinally()
}, () => {
onFinally()
})
}

/**
* Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例
* Promise.all()全部子实例都成功才算成功,有一个子实例失败就算失败。
*/
static all(promises) {
return new myPromise((resolve, reject) => {
const values = [];
promises.forEach(promise => {
promise.then(
res => {
values.push(res);
if (values.length === promise.length) {
resolve(values);
}
},
err => {
reject(err)
}
);
});
});
}

/**
* Promise.race()方法也是将多个 Promise 实例,包装成一个新的 Promise 实例。
* Promise.race()rece是赛跑机制,要看最先的promise子实例是成功还是失败。
*/
static race(promises) {
return new myPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(
res => {
resolve(res);
},
err => {
reject(err);
}
)
})
});
}

/**
* Promise.any()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
* Promise.any()有一个子实例成功就算成功,全部子实例失败才算失败。
*/
static any(promises) {
return new myPromise((resolve, reject) => {
const reasons = [];
promises.forEach(promise => {
promise.then(
res => {
resolve(res);
},
err => {
reasons.push(err)
if(reasons.length === promises.length) {
reject(reasons)
}
}
)
})
})
}
}

防抖和节流

1
2
3
4
5
6
7
8
9
10
11
12
function debounce(fn: Function, delay: number) {
let timer: any = null;
return function() {
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null;
}, delay)
};
}
1
2
3
4
5
6
7
8
9
10
function throttle(fn: Function, delay: number) {
let timer: any = null;
return function () {
if(timer) return;
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null
}, delay)
};
}

快速排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function quickSort(arr: number[], startIndex: number = 0): number[] {
if (arr.length <= 1) return arr;
const right: number[] = [];
const left: number[] = [];
const startNum = arr.splice(startIndex, 1)[0];// 第一个数
for(let i = 0; i < arr.length; i++) {
if(arr[i] < startNum) {
left.push(arr[i]);
} else [
right.push(arr[i]);
]
}
return [...qucikSort(left), startNum, ...qucikSort(right)];
}

输入为两个一维数组,将这两个数组合并,去重,不要求排序,返回一维数组

1
2
3
function dealArr(arr1: any[], arr2: any[]): any[] {
return Array.from(new Set([...arr1, ...arr2]))
}

编写函数convert(money) ,传入金额,将金额转换为千分位表示法。ex:-87654.3 => -87,654.3

思路:判断是否是负数,判断是否有小数点,将整数部分进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function convert(money: number): number {
let result: string = ''; // 用于存放整数部分
let negativeFlag: string = '' // 是否要负号
let tail: string = ''; // 用于存放小数点后面部分
let arr: string[] = [...String(money)];// 字符串数组

// 判断是否为负数
if(arr[0] === '-') {
negativeFlag = '-'
arr.shift()
}

// 判断是否存在小数点
const dotIndex: number = arr.indexOf(".");
if (dotIndex !== -1) {
tail = arr.splice(dotIndex, arr.length - dotIndex).join("");
}

// 处理整数部分加上千分位
result: string = arr.join("").replace(/(?!^)(?=(\d{3})$)/g, ',');
return negativeFlag + result + tail;
}