JavaScript基础知识(二)——手写"源码"

Promise

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
class MyPromise {
//定义三个静态属性,用于记录Promise的状态
static PENDING = "pending"
static FULFILLED = "fulfilled"
static REJECTED = "rejected"

//初始化传入一个执行函数func,并且立即执行
//执行函数func包含两个参数,resolve,reject,这两个参数也都是函数
constructor(func) {
//初始化定义一个状态属性,并且赋初值pending
this.PromiseState = MyPromise.PENDING
//初始化定义一个变量,存储Promise执行之后的值
this.PromiseResult = null

//异步调用处理
this.onFulfilledCallBacks = [] //保存成功的回调函数
this.onRejectedCallBacks = [] //保存失败的回调函数

//resolve,reject需要绑定this,resolve需要单独执行,this需要指向实例
func(this.resolve.bind(this), this.resolve.bind(this))
}
/**
* @description:resolve函数,Promise成功之后的执行
* @param {*} result:定义执行成功的结果
* @return {*}
*/
resolve(result) {
if (this.PromiseState === MyPromise.PENDING) {
//Promise成功之后、,状态属性修改为fulfilled
this.PromiseState = MyPromise.FULFILLED
this.PromiseResult = result
//依次执行回调函数
while (this.onFulfilledCallBacks.length) {
this.onFulfilledCallBacks.shift()(result)
}
}
}

/**
* @description: 定义reject函数,Promise失败之后的执行
* @param {*} reason:定义执行失败的结果
* @return {*}
*/
reject(reason) {
if (this.PromiseState === this.PENDING) {
//Promise失败之后、,状态属性修改为rejected
this.PromiseState = this.REJECTED
this.PromiseResult = reason
//依次执行回调函数
while (this.onRejectedCallBacks.length) {
this.onRejectedCallBacks.shift()(reason)
}
}
}

/**
* @description: then函数实现
* @param {*} onFulfilled:promise成功时执行
* @param {*} onRejected:promise失败时执行
* @return {*}返回一个新的Promise对象
*/
then(onFulfilled, onRejected) {
//参数需要是函数
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (val) => val
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason
}

//then需要返回一个新的Promise对象
const thenpromise = new MyPromise((resolve, reject) => {
//参数处理
const resolvep = (cb) => {
setTimeout(() => {
try {
//
const x = cb(this.PromiseResult)
if (x === thenpromise) {
throw new Error("err")
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
}
})
}

if (this.PromiseState === MyPromise.FULFILLED) {
resolvep(onFulfilled)
} else if (this.PromiseState === MyPromise.REJECTED) {
resolvep(onRejected)
} else {
this.onFulfilledCallBacks.push(resolvep.bind(this, onFulfilled))
this.onRejectedCallBacks.push(resolvep.bind(this, onRejected))
}
})

return thenpromise
}
}

//测试
const mp = new MyPromise((res, rej) => {
setTimeout(() => {
console.log(1)
res(2222)
console.log(3)
})
}).then((s) => {
console.log(s)
})

Promise.all

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
/**
* @description: 所有的promise成功,则返回成功,否则返回失败
* @param {*} promises
* @return {*}
*/
Promise.myAll = (promises) => {
return new Promise((resolve, reject) => {
let count = 0
let result = []
const len = promises.length || 0
if (len === 0) {
return resolve([])
}
promises.forEach((p, i) => {
Promise.resolve(p)
.then((res) => {
count += 1 //成功的promise计数
result[i] = res //成功的promise记录
if (count === len) {
//所有的promise都成功,返回
resolve(result)
}
})
.catch(reject) //有一个promise不成功,直接抛出
})
})
}

Promise.allSettled

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
/**
* @description:所有的promise都返回,不管成功还是失败
* @param {*} promises
* @return {*}
*/
Promise.myAllSettled = (promises) => {
return new Promise((resolve, reject) => {
let counter = 0
const result = []
const len = promises.length || 0
if (len === 0) {
return resolve([])
}
promises.forEach((p, i) => {
Promise.resolve(p).then(
(res) => {
counter += 1
result[i] = {
status: "fulfilled",
value: res
}
if (counter === len) {
resolve(result)
}
},
(rej) => {
counter += 1
result[i] = {
status: "rejected",
value: rej
}
if (counter === len) {
reject(result)
}
}
)
})
})
}

Promise.race

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* @description: 返回最快的promise,不管它成功还是失败
* @param {*} promises
* @return {*}
*/
Promise.myRace = (promises) => {
return new Promise(function (resolve, reject) {
promises.forEach((p) => {
// 当第一个 promise 成功或失败时返回结果
Promise.resolve(p).then(resolve, reject)
})
})
}

Promise.any

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @description: 返回最快的成功promise,如果所有的promise失败,则返回失败的promise
* @param {*} promises
* @return {*}
*/
Promise.myAny = (promises) => {
let counter = 0
return new Promise((resolve, reject) => {
promises.forEach((p) => {
Promise.resolve(p).then(resolve, (err) => {
counter += 1
if (counter === promises.length) {
reject("全都不成功!")
}
})
})
})
}

浅拷贝

1
2
3
4
5
6
7
8
9
10
11
12
//对象
const newobj1 = Object.assign({}, obj)
const newobj2 = { ...obj }

//数组
const newArr1 = Array.from(arr)
const newArr2 = [...arr]
const newArr3 = arr.slice()
const newArr4 = arr.concat([])
const newArr5 = arr.filter((val) => val)
const newArr6 = arr.map((val) => 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
//手写深拷贝
const obj1 = JSON.parse(JSON.stringify(obj))

const obj2 = structuredClone(obj)

function deepClone(obj, wk = new WeakMap()) {
if (obj === null || typeof obj !== "object") return obj
if (obj instanceof Date) return new Date(obj)
if (obj instanceof RegExp) return new RegExp(obj)
if (obj instanceof HTMLElement) return obj

if (wk.has(obj)) {
return wk.get(obj)
}

let target = Array.isArray(obj) ? [] : {}
wk.set(obj, target)
Reflect.ownKeys(obj).forEach((item) => {
if (typeof obj[item] === "object" && obj[item] !== null) {
target[item] = deepClone(obj[item], wk)
} else {
target[item] = obj[item]
}
})
return target
}

数组去重

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

//遍历循环,但是不能去除[] {} function{}
function norepeatArr(arr) {
for (let i = 0, len = arr.length; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j] || Object.is(arr[i], arr[j])) {
arr.slice(j, 1)
}
}
}
return arr
}

//遍历循环,判断索引,但是判断NaN
function norepeatArr(arr) {
let newArr = []
arr.forEach((v, i) => {
if (newArr.indexOf(v) === i) {
newArr.push(v)
}
})
return newArr
}

//遍历循环,根据Map
function norepeatArr2(arr) {
let map = new Map()
arr.forEach((v, i) => {
if (!map.has(v)) {
map.set(v, i)
}
})
return [...map.keys()]
}

//Set
function norepeatArr(arr) {
return [...new Set(arr)] //return Array.from(new Set(arr))
}

多维数组展平

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
//多维数组展平
const newArr = arr.flat(1) //参数表示展平的层级

//reduce遍历循环
function flatArr1(arr) {
if (!arr.length) {
return
}
return arr.reduce((pre, cur) => {
return Array.isArray(cur) ? [...pre, ...flatArr(cur)] : [...pre, cur]
}, [])
}

//迭代
function flatArr2(arr) {
if (!arr.length) return
while (
arr.some((item) => {
return Array.isArray(item)
})
) {
arr = [].concat(...arr)
}
}

//指定展开深度
function flatArr3(arr, depth = 1, resArr = []) {
for (const item of arr) {
if (Array.isArray(item) && depth > 0) {
flatArr2(item, depth - 1, resArr)
} else {
resArr.push(item)
}
}
return resArr
}

防抖和节流

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
//防抖:在一段时间范围内,事件只执行一次
/**
* @description: 防抖
* @param {*} func 需要防抖处理的函数
* @param {*} timer 定时时长
* @param {*} immediate 是否立即执行
* @return {*}返回防抖处理完成之后的函数
*/
function debounce(func, timer = 100, immediate = false) {
//定义定时器,用于记录定时操作
let setTime = null
return function (...args) {
//清除定时器
setTime && clearTimeout(setTime)
//每次调用func时,需要等待timer再执行
const that = this
if (immediate) {
let flag = !setTime
if (flag) {
func.apply(that, args)
}
setTime = setTimeout(() => {
setTime = null
}, timer)
} else {
setTime = setTimeout(() => {
func.apply(that, args) //apply绑定,args,修改this指向调用者
}, timer)
}
}
}

//节流:间隔一定时间执行一次
/**
* @description: 节流:间隔一定时间执行一次
* @param {*} func 需要节流处理的函数
* @param {*} timer 定时时长
* @return {*} 返回需要节流处理的函数
*/
function throttle(func, timer = 2000) {
let t1 = 0 //初始状态
return function (...args) {
const that = this
let t2 = new Date()
if (t2 - t1 >= timer) {
func.apply(that, args)
t1 = new Date()
}
}
}

setInterval

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function mySetInterval(func, delay = 1000, maxcounter = 10) {
let counter = 0
let timer = null
let setfunction = function () {
func.call(null)
counter++
timer = setTimeout(() => {
setfunction()
}, delay)
if (counter > maxcounter) {
timer && clearTimeout(timer)
return
}
}
setTimeout(() => {
setfunction()
}, delay)
}

Object.is

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

//Object.is
/**
* +0 === -0 //true
* Object.is(+0, -0) //false
*
* NaN == NaN //false
* Object.is(NaN, NaN) //true
*/

function myObjectIs(a, b) {
if (a === b)
//判断 +0,-0
/**
* /1/+0 == Infinity
*1/-0 == - Infinity
*/
return a !== 0 || 1 / a === 1 / b
return a !== a && b !== b //判断 NaN,NaN
}

console.log(myObjectIs(1, 1)) //true
console.log(myObjectIs(1, 2)) //false
console.log(myObjectIs([], [])) //false
console.log(myObjectIs([], {})) //false
console.log(myObjectIs(0, 0)) //true
console.log(myObjectIs(+0, +0)) //true
console.log(myObjectIs(+0, -0)) //true
console.log(myObjectIs(NaN, 0)) //false
console.log(myObjectIs(NaN, NaN)) //true

new

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//手写new
/**
* 1.在内存中创建一个新对象
* 2.这个新对象内部的[[prototype]]特性被赋值为构造函数的prototype属性
* 3.构造函数内部的this被赋值为这个新对象(即this指向新对象)
* 4.执行构造函数内部的代码(给新对象添加属性)
* 5.如果构造函数返回非空 对象,则返回该对象;否则,返回刚创建的新对象。
*/
function _new(fn) {
// 1 获取除fn以外的所有arguments
// 使用slice删除arguments第一个元素就得到其他arguments
const args = Array.prototype.slice.call(arguments, 1)
// 新建一个对象 用于函数变对象
const newObj = {}
// 原型链被赋值为原型对象
newObj.__proto__ = fn.prototype
// this 指向新对象
fn.apply(newObj, args)
// 返回这个新对象
return newObj
}

const obj1 = _new(obj,'name1','age1')

apply、call、bind

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
//call
Function.prototype.myCall = function (targetFunc, ...args) {
targetFunc = targetFunc || window //targetFunc为空,就指向window
const symbolKey = Symbol() //定义唯一值存储this
targetFunc[symbolKey] = this //谁调用myCall,this就指向谁,func1.myCall(),this指向func1
const res = targetFunc[symbolKey](...args) //执行方法
delete targetFunc[symbolKey] //删除临时存储值
return res //返回函数执行结果
}

//apply
Function.prototype.myApply = function (targetFunc, args) {
targetFunc = targetFunc || window //targetFunc为空,就指向window
const symbolKey = Symbol() //定义唯一值存储this
targetFunc[symbolKey] = this //谁调用myCall,this就指向谁,func1.myCall(),this指向func1
const res = targetFunc[symbolKey](...args) //执行方法
delete targetFunc[symbolKey] //删除临时存储值
return res //返回函数执行结果
}

//bind
Function.prototype.myBind = function (targetFunc, ...args) {
targetFunc = targetFunc || window //targetFunc为空,就指向window
const symbolKey = Symbol() //定义唯一值存储this
const that = this //谁调用myCall,this就指向谁,func1.myCall(),this指向func1
targetFunc[symbolKey] = this
return function (...innerargs) {
//bind的返回值是一个函数,可以接收参数
if (this instanceof that) {
//使用bina之后的函数如果是个构造函数。可以new的话,this将执行实例
this[symbolKey] = that
this[symbolKey](...[...args, ...innerargs])
}
const res = targetFunc[symbolKey](...[...args, ...innerargs])
return res
}
}

ajax

1
2
3
4
5
6
7
8
9
10
11
12
function ajax(url) {
const xhr = new XMLHttpRequest()
xhr.open("GET", url, false) //false表示同步,true表示异步
xhr.setRequestHeader("Content-Type", "application/json")
xhr.onreadystatechange = function () {
if (xhr.readyState != 4) return
if (xhr.status === 200 || xhr.status == 304) {
console.log(xhr.responseText)
}
}
xhr.send()
}