代码实践篇

1、求数组中指定顺序的最大值

编写方法,接收两个参数(index, arr)。返回arr数组中第index个最大对的数字。如果里面有大小相同则并列排名。

1.1 示例

1
2
const arr = [3, 10, 20, 22, 33, 1, 20, 44, 44, 55]
console.log(getIndexMaxNumber(3, arr)) // output 33

1.2 代码实现

1
const getIndexMaxNumber = (index, arr) => [...new Set(arr.sort((a, b)=>b - a))][index - 1]

2、实现列表拖拽排序

2.1 前置知识

  • dragstart 拖动开始
  • drag 拖动中
  • drag 拖动结束
  • dragenter 到达放置目标时
  • dragover 放置目标内移动时
  • dragleave 离开放置目标时
  • drop 放到放置目标中时

2.2 HTML部分

1
2
3
4
5
6
7
<ul>
<li draggable="true"></li>
<li draggable="true"></li>
<li draggable="true"></li>
<li draggable="true">绿</li>
<li draggable="true"></li>
</ul>

2.3 JavaScript部分

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
let ul = document.querySelector(".list")

ul.ondragover = e => {
// 在防止目标上移动时,阻止默认事件
e.preventDefault()
}

// 存放被拖动元素
let draging
ul.ondragstart = e => {
// 拖动开始时,将当前选中的元素保存起来
draging = e.target
}

ul.ondrop = e => {
// 存储放置目标元素
let target = e.target
// 判断是否是li,并且不是一开始拖动的元素
if (target.nodeName === "LI" && target !== draging) {
// 如果拖动元素的下标小于放置的下标
if (getIndex(draging) < getIndex(target)) {
target.parentNode.insertBefore(draging, target.nextSibling);
} else {
target.parentNode.insertBefore(draging, target);
}
}
};
// 获取当前元素index
const getIndex = el => {
// 默认下标为0
let index = 0;
if (!el || !el.parentNode) {
return -1;
}
// 往上找有没有同级元素,如果有就下标加1
while (el = el.previousElementSibling) {
index++;
}
return index;
}

3.如何终止请求

3.1 HTML部分

1
2
<button class="startBtn">点击请求</button>
<button class="stopBtn">点击停止</button>

3.2 JS部分

1
2
3
4
5
6
7
8
9
10
11
12
const xhr = new XMLHttpRequest()
document.querySelector('.startBtn').onclick = function(){
xhr.open('get','/api',true)
xhr.onload = fucntion(){
console.log(xhr.responseText)
}
xhr.send()
}
document.querySelector('endStart').onclick = function(){
console.log('停止请求')
xhr.abort()
}

4、Promise.allSettled是什么,简单实现一下

allSettled是ES2020新特性,可以获取多个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
function MyallSettled(list){
let resArr = new Array(list.length);
let num = 0
return new Promise(resolve => {
list.forEach((item, key) => {
let obj = {};
item.then(res => {
obj['status'] = "fulfilled";
obj.value = res;
resArr[key] = obj;
num++
if (num === list.length) {
resolve(resArr);
}
}, err => {
obj['status'] = "rejected";
obj.reson = err;
resArr[key] = obj;
num++
if (num === list.length) {
resolve(resArr);
}
})
})
});
}

5、可选链语法

1
2
3
4
5
6
7
8
9
10
11
const a = {
b: null,
c: {},
d: false
}

console.log(a?.b ?? 1, '-') // 1
console.log(a?.b?.c ?? 1, '--') // 1
console.log(a?.c ?? 1, '---') // {}
console.log(a?.d ?? 1, '----') // false
console.log(a?.d?.c ?? 1, '-----') // 1

6、instanceof

1
2
3
4
5
6
console.log(({}) instanceof Object, '-')
console.log(({}) instanceof Function, '--')
console.log(Function instanceof Object, '---')
console.log(Function instanceof Function, '----')
console.log(Object instanceof Object, '-----')
console.log(Object instanceof Function, '------')

7、实现一个sleep函数

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
function sleep1(sleepTime) {
const start = new Date()
while (new Date - start < sleepTime) { }
}

console.log(1)
sleep1(1000)
console.log(2)

function sleep2(sleepTime) {
for (let start = new Date; new Date - start <= sleepTime;) { }
}

console.log(3)
sleep2(1000)
console.log(4)

function sleep3(sleepTime) {
return new Promise(resolve => setTimeout(resolve, sleepTime))
}

console.log(5)
sleep3(1000).then(() => console.log(6))

!async function () {
console.log(7)
await sleep3(1000)
console.log(8)
}()

8、计算今天星期几

1
2
3
4
5
6
7
8
9
function getDay(date){
const nowDate = new Date(date)
const nowDay = nowDate.getDay()
const dayMap = ['星期天','星期一','星期二','星期三','星期四','星期五','星期六']
return dayMap[nowDay]
}

const nowTime = new Date()
console.log(getDay(nowTime.toISOString()))

9、并且或

1
2
3
4
5
6
7
var string = 'string'
var number = 0
var bool = true
console.log(number || string) // string
console.log(number && string) // 0
console.log(bool || number) // true
console.log(bool && number) // 0

10、实现查找字符串的下标

1
2
3
4
5
6
7
8
function getIndex(str, searchValue, fromIndex) {
if (fromIndex < 0 || fromIndex === undefined) fromIndex = 0
if (fromIndex > str.length) return -1
for (let index = fromIndex; index < str.length; index++) {
if(str.charAt(index) === searchValue) return index
}
return -1
}

11、Promise实现红绿灯交换效果

3秒亮红灯,1秒亮绿灯,2秒亮黄灯。持续交替

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 red = () => console.log('red')

const green = () => console.log('green')

const yellow = () => console.log('yellow')

const myLight = (cb, timer) => {
return new Promise(resolve=>{
setTimeout(()=>{
cb()
resolve()
}, timer)
})
}

const setup = () => {
Promise.resolve().then(()=>{
return myLight(red, 3000)
}).then(()=>{
return myLight(green, 1000)
}).then(()=>{
return myLight(yellow, 2000)
}).then(()=>setup())
}

setup()

12、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
const timeout = ms =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, ms)
})

const ajax1 = () =>
timeout(2000).then(() => {
console.log('1')
return 1
})

const ajax2 = () =>
timeout(1000).then(() => {
console.log('2')
return 2
})

const ajax3 = () =>
timeout(2000).then(() => {
console.log('3')
return 3
})

// 顺序执行
const mergePromise = ajaxArray => {
const dataList1 = []
let parentPromise = Promise.resolve()
ajaxArray.forEach(pItem => {
parentPromise = parentPromise.then(pItem).then(res => {
dataList1.push(res)
return dataList1
})
})
return parentPromise
}

mergePromise([ajax1, ajax2, ajax3]).then(data => {
console.log('done1')
console.log(data) // data 为 [1, 2, 3]
})

// 等价于

const dataList2 = []
ajax1()
.then(res => {
dataList2.push(res)
return ajax2()
})
.then(res => {
dataList2.push(res)
return ajax3()
})
.then(res => {
dataList2.push(res)
console.log('done2')
console.log(dataList2)
})

12、柯里化函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function curry (fn) {
return function curryFn (...args) {
if (args.length < fn.length) {
return function () {
return curryFn(...args.concat(Array.from(arguments)))
}
}
return fn(...args)
}
}

const add1 = (a, b, c) => {
return a + b + c * 2
}
const add2 = (a, b, c, d, e) => {
return a * b + c + d + e
}
const curry1 = curry(add1)
const curry2 = curry(add2)
console.log(curry1(1)(2)(3))
console.log(curry2(1)(2)(3)(4)(5))

13、compose函数

1
2
3
4
5
6
7
8
9
10
11
12
function one (num) {
return num + 1
}
function two (num) {
return num * 2
}
function compose (...fn) {
return function (args) {
return fn.reverse().reduce((result, fn) => fn(result), args)
}
}
console.log(compose(one, two)(1))

14、go函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function go(...args) {
let o = 'o'
function next(...args) {
if(args[0] === undefined) {
o += 'o'
return next
}else{
return 'g' + o + args[0]
}
}
return next(...args)
}

console.log(go('l'))
console.log(go()('l'))
console.log(go()()('l'))
console.log(go()()()()('l'))
console.log(go()()()()()('l'))

15、实现myMap函数

1
2
3
4
5
6
7
8
9
const arr = [1,2,3,4,5,6,7]
Array.prototype.myMap = function (cb) {
const newArr = []
this.forEach((item, index) => {
newArr.push(cb(item, index))
})
return newArr
}
console.log(arr.myMap(item=>item+1))

16、打乱数组顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 通过 sort
function confusion (arr) {
const newArr = [...arr]
arr.sort(() => Math.random() - .5)
return newArr
}

// 通过洗牌算法
function confusion () {
const newArr = [...arr]
for(let i = newArr.length; i>0;) {
const index = parseInt(Math.random() * --i)
const temp = newArr[i]
newArr[i] = newArr[index]
newArr[index] = temp
}
return newArr
}

17、异步执行顺序例题

17.1

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
const promise1 = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('success')
console.log('timer 1')
}, 1000)
console.log('promise1 的内容')
})

const promise2 = promise1.then(()=>{
throw new Error('error!!!')
})

console.log('promise1', promise1)
console.log('promise2', promise2)

setTimeout(()=>{
console.log('timer2')
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)

// promise1 的内容
// promise1 padding
// promise2 padding
// timer1
// throw error!!!
// timer2
// promise1 fulfilled success
// promise2 rejected error

17.2

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
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}

async function async2() {
console.log('async2 start')
await async3()
console.log('async2 end')
}

async function async3() {
console.log('async3')
}

async1()
console.log('start')

// async1 start
// async2 start
// async3
// start
// async2 end
// async1 end

18、TS编写工具函数,获取函数的参数类型

1
2
3
4
5
6
7
function sayName (name: string, age: number) {
console.log('我叫' + name + ',今年' + age + '岁')
}

type GetParamsType<T> = T extends (...args: infer P) => any ? P : never

type SayNameParamsType = GetParamsType<typeof sayName>

19、TS编写工具函数,筛选指定类型

1
2
3
4
5
6
7
8
9
10
11
12
type Model = {
name: string;
getName: () => string;
age: number;
getAge: () => number;
}

type TypeKeys<T> = T[keyof T]

type GetNewModel<T, K> = Pick<T, TypeKeys<{ [P in keyof T]: [T[P]] extends [K] ? [K] extends [T[P]] ? P : never : never }>>

type NewModel = GetNewModel<Model, string>

20、使用递归实现,0 1 2 3 6 11…

1
暂未实现

21、随机删除数字,乱序后,找出删除的数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

function dispose(arr: number[]) {
const newArr = [...arr]
// 减少数字
for (let i = 0; i < 5; i++) {
const index = Math.floor(Math.random() * newArr.length)
newArr.splice(index, 1)
}
// 打乱顺序
return newArr.sort(() => Math.random() * 10 - 10)
}
// 查找减少数字
function find(target: number[], arr: number[]) {
const map: Map<number, unknown> = new Map()
arr.forEach(cur => {
map.set(cur, 1)
})
return target.filter(cur => !map.has(cur))
}

const test = dispose(arr)
console.log(find(arr, test), test)

22、实现instanceof

1
2
3
4
5
6
7
8
9
function myInstanceof(a, b) {
let L = Object.getPrototypeOf(a)
let R = b.prototype
while (true) {
if (L === null) return false
if (L === R) return true
L = Object.getPrototypeOf(L)
}
}

生成 100 个长度为 10 的随机字符串

1

判断两个非负整数为 0

1
2
3
function isZero(a, b) {
return a + b === 0
}