防抖
// 防抖
(() => {
const debounce = (fn: Function, delay = 1000): Function => {
let timer;
return function (...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
const d = debounce((a) => {
console.log(a);
}, 300);
setInterval(() => {
d('sssss');
}, 350);
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
节流
// 节流
(() => {
const throttle = (fn: Function, delay = 1000) => {
let flag = false;
return function (...args) {
if (flag) return;
setTimeout(() => {
fn.apply(this, args);
flag = false;
}, delay);
flag = true;
};
};
const t = throttle((name) => {
console.log(name);
}, 1000);
setInterval(() => {
t('chenzilin');
}, 1);
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
New
// new
(() => {
const New = function (fn: Function, ...args) {
const obj = Object.create(fn.prototype);
const res = fn.apply(obj, args);
if (typeof res === 'function' || (typeof res === 'object' && res !== null)) {
return res;
}
return obj;
};
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name);
};
const obj = New(Person, 'czl', 18);
console.log(obj);
obj.sayName();
function TestFun() {
this.name = 'ccc';
return {
name: 'aaa'
};
}
const tf = New(TestFun);
console.log(tf);
})();
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
Bind
// bind
(() => {
Function.prototype.bind2 = function (context, ...args1) {
// this指向调用的函数
const fn = this;
const resFn = function (...args2) {
// this指向对象
return fn.apply(this instanceof fn ? this : context, args1.concat(args2));
};
resFn.prototype = Object.create(fn.prototype);
return resFn;
};
const obj = {};
const Person = function (name, age) {
this.name = name;
this.age = age;
};
Person.prototype.sayName = function () {};
const p = Person.bind2(obj, 'czl');
p(19);
console.log(obj);
const o = new p(29);
console.log(o);
console.log(o.sayName);
})();
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
Call
// call
(() => {
Function.prototype.call2 = function (context, ...args) {
const key = Symbol('key');
context[key] = this;
const res = context[key](...args);
delete context[key];
return res;
};
const obj = {
name: '',
age: 0
};
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.call2(obj, 'czl', 19);
console.log(obj);
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Apply
// apply
(() => {
Function.prototype.apply2 = function (context, args) {
const key = Symbol('key');
context[key] = this;
const res = context[key](...args);
delete context[key];
return res;
};
const obj = {
name: '',
age: 0
};
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.apply2(obj, ['czl', 29]);
console.log(obj);
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
DeepClone
// 深拷贝
(() => {
const deepClone = (target, cache = new WeakMap()) => {
if (!(target instanceof Object)) return target;
if (cache.has(target)) {
return cache.get(target);
} else if (target instanceof Date) return new Date(target);
else if (target instanceof RegExp) return new RegExp(target.source, target.flags);
const res = Array.isArray(target) ? [] : {};
cache.set(target, res);
Object.keys(target).forEach((key) => {
if (target[key] instanceof Object) {
res[key] = deepClone(target[key], cache);
} else {
res[key] = target[key];
}
});
return res;
};
const obj = {
name: 'zhangsan',
hobby: {
basketball: true,
swim: true
},
cars: ['玛莎拉蒂', '保时捷', '布加迪威龙'],
say() {
console.log(this.name);
},
obj: null
};
obj.obj = obj;
// 浅拷贝
// const copyObj = Object.assign({}, obj);
// copyObj.name = 'lisi';
// console.log(obj.name);
// copyObj.hobby.basketball = false;
// console.log(obj.hobby.basketball);
// copyObj.cars.splice(2, 1);
// console.log(obj.cars);
const newObj = deepClone(obj);
newObj.name = 'lisi';
console.log(obj.name);
newObj.hobby.basketball = false;
console.log(obj.hobby.basketball);
newObj.cars.splice(2, 1);
console.log(obj.cars);
newObj.obj = 123;
console.log(obj.obj);
})();
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
柯里化
// 柯里化
(() => {
const curry = function (fn: Function) {
return function curried(...args1) {
if (args1.length >= fn.length) {
return fn.apply(this, args1);
}
return function (...args2) {
return curried.apply(this, args1.concat(args2));
};
};
};
const sum = (a, b, c) => {
return a + b + c;
};
const currySum = curry(sum);
console.log(currySum(1)(2, 3));
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ES5继承
// es5继承
(() => {
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log(this.name);
};
function Children(name, age) {
Person.call(this, name);
this.age = age;
}
Children.prototype.sayAge = function () {
console.log(this.age);
};
Object.setPrototypeOf(Children.prototype, Person.prototype);
Children.prototype.constructor = Children;
const zs = new Children('张三', 20);
zs.sayName();
zs.sayAge();
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ES6继承
// es6继承
(() => {
class Person {
constructor(private name) {}
sayName() {
console.log(this.name);
}
static callMe() {
console.log('callMe');
}
}
class Children extends Person {
constructor(name, private age) {
super(name);
}
sayAge() {
console.log(this.age);
}
static callMe() {
console.log('callMe111');
}
}
const zs = new Children('张三', 20);
zs.sayName();
zs.sayAge();
Children.callMe();
})();
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
InstanceOf
// instanceof
(() => {
function myInstanceof(left, right: Function) {
let proto = left.__proto__;
let prototype = right.prototype;
while (true) {
if (proto === prototype) return true;
else if (!proto) return false;
proto = proto.__proto__;
}
}
console.log(myInstanceof({}, Object));
console.log(myInstanceof([], Object));
console.log(myInstanceof({}, Array));
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
数组扁平化
// 数组扁平化
(() => {
const flattening = (arr: any[]) => {
return arr.reduce((pre, cur) => (Array.isArray(cur) ? [...pre, ...flattening(cur)] : [...pre, cur]), []);
};
console.log(flattening([1, [3, 4, [5]], 8]));
})();
1
2
3
4
5
6
7
8
数组去重
// 数组去重
(() => {
const uniqueArr = (arr: any[]) => {
return [...new Set(arr)];
};
console.log(uniqueArr([1, 2, 3, 1, 2, 3, 4, 4, 4, 7, 7, 7, 2]));
})();
1
2
3
4
5
6
7
对象扁平化
// 对象扁平化
(() => {
const flatObj = (obj) => {
const res = {};
function process(key, value) {
if (!(value instanceof Object)) {
res[key] = value;
} else if (Array.isArray(value)) {
value.forEach((item, index) => {
process(`${key}[${index}]`, item);
});
} else if (value instanceof Object) {
for (let k in value) {
process(key ? `${key}.${k}` : `${k}`, value[k]);
}
}
}
process('', obj);
return res;
};
function isObjectValueEqual(a, b) {
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
var propA = a[propName];
var propB = b[propName];
if (propA !== propB) {
return false;
}
}
return true;
}
// 实现一个 flatten 函数,实现如下的转换功能
const obj = {
a: 1,
b: [1, 2, { c: true }],
c: { e: 2, f: 3 },
g: null
};
// 转换为
let objRes = {
a: 1,
'b[0]': 1,
'b[1]': 2,
'b[2].c': true,
'c.e': 2,
'c.f': 3,
g: null
};
console.log(flatObj(obj));
console.log(Object.is(flatObj(obj), objRes)); // false
console.log(isObjectValueEqual(flatObj(obj), objRes)); // true
})();
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
JSON.parse
// JSON.parse
(() => {
const parse = (target: string) => {
return eval(`(${target})`);
};
const obj = {
name: 'czl',
age: 19,
interests: ['a', 'b', 'c']
};
const st = JSON.stringify(obj);
console.log(st);
console.log(parse(st));
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
JSON.stringify
// JSON.stringify
(() => {
const getType = (target) => {
return typeof target === 'symbol' ? 'Symbol_basic' : Object.prototype.toString.call(target).slice(8, -1);
};
const isObject = (o) => {
return o !== null && (typeof o === 'object' || typeof o === 'function');
};
const processOtherTypes = (target, type: string) => {
switch (type) {
case 'String':
return `"${target.valueOf()}"`;
case 'Number':
case 'Boolean':
return target.valueOf().toString();
case 'Symbol':
case 'Error':
case 'RegExp':
return '{}';
case 'Date':
return `"${target.toJSON()}"`;
case 'Function':
return undefined;
default:
return null;
}
};
// 检查循环引用
const checkCircular = (obj, currentParent) => {
let type = getType(obj);
if (type === 'Object' || type === 'Array') {
if (currentParent.includes(obj)) {
throw new TypeError('Converting circular structure to JSON');
}
currentParent.push(obj);
}
};
const jsonStringify = (target, initParent = [target]) => {
let type = getType(target);
const iterableList = ['Object', 'Array', 'Arguments', 'Set', 'Map'];
const specialList = ['Undefined', 'Symbol_basic', 'Function'];
if (!isObject(target)) {
if (type === 'Symbol_basic' || type === 'Undefined') {
return undefined;
} else if (Number.isNaN(target) || target === Infinity || target === -Infinity) {
return 'null';
} else if (type === 'String') {
return `"${target}"`;
}
return String(target);
} else {
let res;
// 针对new String()这种不可迭代的对象
if (!iterableList.includes(type)) {
res = processOtherTypes(target, type);
}
// 可迭代对象
else {
// Array
if (type === 'Array') {
res = target.map((item) => {
if (specialList.includes(getType(item))) {
return 'null';
} else {
// 判断循环引用
let currentParant = [...initParent];
checkCircular(item, currentParant);
return jsonStringify(item, currentParant);
}
});
res = `[${res}]`.replace(/'/g, '"');
}
// Object
else {
res = [];
Object.keys(target).forEach((key) => {
if (getType(key) !== 'Symbol_basic') {
let type = getType(target[key]);
if (!specialList.includes(type)) {
let currentParant = [...initParent];
checkCircular(target[key], currentParant);
res.push(`"${key}":${jsonStringify(target[key], currentParant)}`);
}
}
});
res = `{${res}}`.replace(/'/g, '"');
}
}
return res;
}
};
console.log(jsonStringify(() => {})); // undefined
console.log(jsonStringify(undefined)); // undefined
console.log(jsonStringify('123')); // '"123"'
console.log(jsonStringify(123)); // '123'
console.log(jsonStringify(null)); // 'null'
console.log(jsonStringify(Symbol('key'))); // undefined
console.log(jsonStringify(NaN)); // null
console.log(jsonStringify(true)); // 'true'
console.log(jsonStringify({ x: 5 })); // '{"x": 5}'
console.log(jsonStringify([1, 'false', false]));
console.log(jsonStringify({ b: undefined }));
console.log(jsonStringify({ b: 'name' }));
console.log(jsonStringify(Symbol('name'))); // undefined
console.log(jsonStringify([Symbol('name'), Symbol('name'), Symbol('name')])); // [null, null, null]
console.log(jsonStringify(/test/)); // {}
console.log(jsonStringify(new Error('error'))); // {}
const map = new Map();
map.set('name', '张三');
console.log(jsonStringify(map)); // {}
console.log(jsonStringify({ name: [1, '2', true, null, undefined, Symbol('key'), function say() {}, /123/, [], new Error('error'), new Map(), new Set()] }));
})();
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
事件触发器
// 事件触发器
(() => {
class EventEmitter {
cache: Record<string, Function[]> = {};
on(name: string, fn: Function) {
const tasks = this.cache[name];
if (!tasks) {
this.cache[name] = [fn];
} else {
this.cache[name].push(fn);
}
}
emit(name: string, once = false) {
const tasks = this.cache[name].slice();
if (tasks) {
tasks.forEach((fn) => {
fn();
});
if (once) {
delete this.cache[name];
}
}
}
off(name: string, fn: Function) {
const tasks = this.cache[name];
if (tasks) {
const index = tasks.findIndex((f) => f === fn);
if (index !== -1) {
tasks.splice(index, 1);
}
}
}
}
const task1 = () => {
console.log('task1');
};
const task2 = () => {
console.log('task2');
};
const event = new EventEmitter();
event.on('task', task1);
event.on('task', task2);
event.off('task', task2);
setTimeout(() => {
event.emit('task');
}, 1000);
})();
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
Promise
// es6 Promise
(() => {
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
reject(new TypeError('检测Promise循环引用'));
} else if (x instanceof MyPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
};
class MyPromise {
status = PENDING;
value: string;
reason = null;
resolveCallbackList = [];
rejectCallbackList = [];
constructor(private fn) {
try {
fn(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
while (this.resolveCallbackList.length) {
this.resolveCallbackList.shift()(this.value);
}
}
};
reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
while (this.rejectCallbackList.length) {
this.rejectCallbackList.shift()(this.reason);
}
}
};
then(onFulfilled, onRejected = null) {
const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
const realOnRejected =
typeof onRejected === 'function'
? onRejected
: (reason) => {
throw reason;
};
const promise2 = new MyPromise((resolve, reject) => {
const microtaskFulfilled = () => {
queueMicrotask(() => {
try {
const x = realOnFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
const microtaskRejected = () => {
queueMicrotask(() => {
try {
const x = realOnRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
if (this.status === FULFILLED) {
microtaskFulfilled();
} else if (this.status === REJECTED) {
microtaskRejected();
} else {
this.resolveCallbackList.push(microtaskFulfilled);
this.rejectCallbackList.push(microtaskRejected);
}
});
return promise2;
}
catch(onRejected) {
this.then(null, onRejected);
}
static resolve(value) {
return new MyPromise((resolve) => {
resolve(value);
});
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
static race(list: MyPromise[]) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < list.length; i++) {
list[i]
.then((val) => {
resolve(val);
})
.catch((err) => {
reject(err);
});
}
});
}
static all(list: MyPromise[]) {
const resList = [];
let count = 0;
return new MyPromise((resolve, reject) => {
for (let i = 0; i < list.length; i++) {
list[i]
.then((val) => {
count++;
resList.push(val);
if (count === list.length) {
resolve(resList);
}
})
.catch((err) => {
reject(err);
});
}
});
}
}
const p1 = new MyPromise((resolve) => {
resolve(111);
}).then((val) => {
console.log(val);
return 222;
});
const p2 = p1
.then((val) => {
console.log(val);
return 333;
})
.then((val) => {
console.log(val);
return p1;
})
.then((val) => {
console.log(val);
return 111;
});
MyPromise.resolve('你好').then((res) => {
console.log(res);
});
MyPromise.reject('reject').catch((err) => {
console.log(err);
});
const race1 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('race1');
}, 200);
});
const race2 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('race2');
}, 500);
});
MyPromise.race([race1, race2]).then((val) => {
console.log(val);
});
MyPromise.all([race1, race2]).then((val) => {
console.log(val);
});
})();
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
Async/Await
// async/await
(() => {
const async = (genertor) => {
const iterator = genertor();
function handle(iteratorResult) {
if (iteratorResult.done) return;
const itertorValue = iteratorResult.value;
if (itertorValue instanceof Promise) {
itertorValue.then((res) => handle(iterator.next(res))).catch((err) => iterator.throw(err));
}
}
try {
handle(iterator.next());
} catch (error) {
iterator.throw(error);
}
};
const fn = (i) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(++i);
}, i * 300);
});
};
async(function* () {
const val1 = yield fn(2);
console.log(val1);
const val2 = yield fn(val1);
console.log(val2);
const val3 = yield fn(val2);
console.log(val3);
return val3;
});
})();
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