节流 & 防抖
节流:用户频繁点击按钮,但只能3秒(timer)才执行一次
1 | // 节流:技能冷却中 |
防抖:用户频繁拖动操作,希望拖动停止后再实现一个效果
1 | // 回城被打断 |
发布订阅模式
1 | const eventHub = { |
用class实现
1 | class EventHub { |
手写AJAX
1 | var request = new XMLHttpRequest() |
简易版Promise
1 | class Promise2 { |
Promise.all
- 在Promise上写,而不是原型
- 参数是一个Promise数组,返回值是一个新Promise对象
- 用一个数组来记录结果
- 只要有一个reject,就整体reject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Promise.myAll = function(list){
const results = []
let count = 0 // 表示成功resolve的数量,当const等于list的长度时,说明全部成功
return new Promise((resolve,reject) =>{
list.map((promise,index) => {
promise.then((result) => {
results[index] = result // 将成功的结果记录在results里
count += 1
if(count === list.length) { // 全部成功后调用resolve
resolve(results)
}
}, (reason) => {
reject(reason)
})
})
})
}
深拷贝
- 方法一:用JSON
- 该方法不支持日期、正则、函数、undefined等数据
- 不支持引用
1
const b = JSON.parse(JSON.stringify(a))
- 方法二:用递归
- 检查环:a.self = a 造成的无法退出递归的问题,使用缓存cache
- 不拷贝原型上的属性(hasOwnProperty)
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
58const deepClone = (a, cache) => {
if(!cache){
// 只有第一次深拷贝时创建缓存,后面递归的不会再创建
// 使用Map而不是Object,Map的键可以是对象、函数,而Object的键只能是string/symbol
cache = new Map() // 使用Map做映射,只要曾经拷贝过,就不会重复拷贝
}
if(a instanceof Object){
// 判断是对象的实例
if(cache.get(a)) { return cache.get(a) } // 检查环,因为a.self = a 无法退出递归
let result
if(a instanceof Function){
if(a.prototype) { // 有 prototype 就是普通函数
result = function(){ return a.apply(this, arguments) }
} else { // 否则就是箭头函数
result = (...args) => { return a.call(undefined, ...args) }
}
} else if (a instanceof Array) {
result = []
} else if (a instanceof Date) {
result = new Date(a-0)
} else if (a instanceof RegExp) {
result = new RegExp(a.source, a.flags)
} else {
result = {}
}
cache.set(a, result)
for(let key in a) {
if(a.hasOwnProperty(key)){ // 只要自身属性,不拷贝原型上(继承)的属性
result[key] = deepClone(a[key], cache)
}
}
return result
} else {
// 其他基本类型
return a
}
}
const a = {
number:1, bool:false, str:'1', empty1:undefined, empty2:null,
array: [
{name:'tony', age: 18},
{name:'joyce', age: 24}
],
date: new Date(2000,0,1,20,30,0),
regex: /\.(j|t)sx/i,
object: {name:'joyce', age: 24},
f1: (a,b) => a+b,
f2: function(a,b){ return a+b }
}
a.self = a
const b = deepClone(a)
b.self === b // true
b.self = 'hello'
a.self !== 'hello' // true
数组去重
方法一:使用Set
1
2
3
4
5
6var a1 = [1,2,2,3,3,3]
var unique = function(a){
return Array.from(new Set(a)) // return [...new Set(a)]
}
unique(a1) // 打印 [1,2,3]方法二:使用计数排序,但只支持字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19var a1 = [1,2,2,3,3,3]
var unique = function(a){
var map = {}
for(let i=0; i<a.length; i++) {
let number = a[i] // 1 ~ 3
if(number === undefined) { continue }
if(number in map) { continue }
map[number] = true
}
// map = {1:true, 2:true, 3:true}
return Object.keys(map)
// 不用Object.keys的写法
const result = []
for(let key in map) {
result.push(key)
}
return result
}方法三:使用Map,但兼容性稍差
1
2
3
4
5
6
7
8
9
10
11
12
13
14var a1 = ['1',1,,2,,2,3,3,3,4,1,2]
var unique = function(a){
var map = new Map()
for(let i=0; i<a.length; i++){
let number = a[i] // 1 ~ 3
if(number === undefined) { continue }
if(map.has(number)){
continue
}
map.set(number, true)
}
return [...map.keys()]
}