目录
Promise调用
Set
递归
有一个楼梯,每次可以走1个台阶或2个台阶,总共有几种走法
计算1~100之和
数组
求数组中最大值
迭代(遍历)数组
扁平化数组
使用flat
toString()
手写递归
使用while
数组倒序
对象
对象属性遍历
扁平化对象
Promise调用
Promise中的resolve和reject不会影响Promise其他代码的运行,也不会影响promiseFun实例中链式的调用
比如:下面的new Promise()调用了reject(),promise中的代码正常运行,实例中的链式调用,会先走catch的调用,后面的.then()也会依次调用,直至回调完所有的.then()
const promiseFun = (...reg) => {
return new Promise((resolve,reject) => {
console.log('1')
reject()
console.log('2')
resolve()
console.log('test')
})
}
onMounted(() => {
promiseFun({a:1}).then(() => {
console.log('1')
}).catch(() => {
console.log('2')
}).then(() => {
console.log('3')
}).catch(() => {
console.log('4')
}).then(() => {
console.log('5')
}).catch(() => {
console.log('6')
}).then(() => {
console.log('7')
}).catch(() => {
console.log('8')
})
})
结果:1 2 test 2 3 5 7
如果先调用resolve(),Promise()中的代码正常运行,实例中的链式调用,只会调用.then()也就只有完成状态,不会调用.catch()
const promiseFun = (...reg) => {
return new Promise((resolve,reject) => {
console.log('1')
resolve()
console.log('2')
reject()
console.log('test')
})
}
结果:1 2 test 1 3 5 7
Set
集合数据类型,也具有增删改查等属性,但和数组不同,不会有重复的数据,
let data = [
{
id: 1,
name:'title1'
},
{
id: 2,
name:'title2'
},
{
id: 3,
name:'title3'
},
{
id: 4,
name:'title4'
},
]
let a1 = new Set(data.map((item) => item.id))
console.log('a1:',a1)
// 使用has判断id为2的值是否存在
// console.log(a1)// true
// 使用has判断id为6的值是否存在
// console.log(a1.has(6))// false
// 获取set的length
console.log('length:',a1.size)
// 往set中添加数据
a1.add({id:5,name:'title5'})
console.log('after:',a1)
递归
有一个楼梯,每次可以走1个台阶或2个台阶,总共有几种走法
function n1(n){
if (n === 1 ) return 1
if (n === 2 ) return 2
console.log('n:',n)
return n1(n - 1) + n1(n - 2)
}
console.log('总共有',n1(4), '种走法') // 总共有 5 种走法
计算1~100之和
// 求1~100和
const numb = (n) => {
if(n === 1) return 1
return numb(n - 1) + n
}
// 步骤解析:
// 参数为1时
// 函数走到if(n === 1) return 1 返回1,后面的return不会执行
// 参数为2时
// 函数走到if(n === 1) n不等于1,执行下面的return,回调函数自己
// numb(2-1=1)回到参数为1的时候,return 为1,这时候numb(n-1) + n,即1+2=3,
// 参数为3时
// 函数走到if判断,执行下面的return,回调函数自己numb(3-1=2),也就到了参数为2的状态了,以此类推。
console.log("求1~100和:",numb(100)) // 求1~100和: 5050
这个函数通过递归的方式实现了求和的功能。每次递归调用都会将问题规模缩小(即n减1),直到达到基本情况(n等于1)。在达到基本情况后,递归开始逐层返回,每层都将当前的n值加到之前的结果上,最终得到从1到n的总和。
例如,调用numb(5)
的过程如下:
-
numb(5)
调用numb(4)
并加上5 -
numb(4)
调用numb(3)
并加上4 -
numb(3)
调用numb(2)
并加上3 -
numb(2)
调用numb(1)
并加上2 -
numb(1)
返回1(递归终止)
然后,这些调用依次返回并累加:
-
numb(2)
返回 1+2=3 -
numb(3)
返回 3+3=6 -
numb(4)
返回 6+4=10 -
numb(5)
返回 10+5=15
因此,numb(5)
的结果是15,这也就是1到5的和。
数组
求数组中最大值
// 数组求和
let arr:Array<number> = reactive([10,2,3,46,986,982,5,90,6])
const findMax = (arr:Array<number>):number => {
if (arr.length == 0) return null
if (arr.length == 1) return 1
if (arr.length === 2) {
return arr[0] >= arr[1] ? arr[0] : arr[1]
}
let length1 = Math.floor(arr.length/2)
let left = findMax(arr.slice(0,length1))
let right = findMax(arr.slice(length1))
return left >= right ? left : right
}
console.log('获取数组中最大值:',findMax(arr))
// 获取数组中最大值: 986
步骤解析
1:函数中先判断入参length为0,1和2的情况,直接return
2:Math.floor()向下取整,获取值,截取数据
3:调用函数本身重走第一步第二步,再到第三步,在length为2时取最大值
4:最终的两个值再进行比较,取最大值;
迭代(遍历)数组
// 迭代数组
let arr:Array<number> = reactive([10,2,3,46,986,982,5,90,6])
const iteration = (arr:Array<number>):number => {
if (arr.length == 0 || arr.length == 1) return arr[0]
console.log(arr[0])
iteration(arr.slice(1))
}
iteration(arr) // 10,2,3,46,986,982,5,90,6
步骤解析:
1:判断数组length为0或为1时,返回下标为0的值
3:数组length大于2时,使用slice截取不是第一位的值,再次调用函数本身进行,依次类推,迭代数组
扁平化数组
使用flat
创建一个新的数组,并根据指定深度递归地将所有子数组元素拼接到新的数组中
let arr = [1,[2,[3,4,5,[6,[7,8,9,10]]]]]
console.log(arr.flat(2)) // [1,2,3,4,5,[6,[7,8,9,10]]]
console.log(arr.flat(3)) // [1, 2, 3, 4, 5, 6, [7, 8, 9, 10]]
console.log(arr.flat(Infinity)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
toString()
let arr = [1,[2,[3,4,5,[6,[7,8,9,10]]]]]
console.log('使用toString:',arr.toString())
let arr1 = arr.toString().split(',').map((item) => {
return item
})
console.log('扁平化后的数组arr:',arr1) // ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
手写递归
// 递归
const iteration = (arr:any[]): Array<number> =>{
let arrResult = []
for (let i in arr) {
if (Array.isArray(arr[i])){
arrResult = arrResult.concat(iteration(arr[i]))
} else {
arrResult.push(arr[i])
}
}
return arrResult
}
console.log('扁平化之后的数组:',iteration(arr))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
reduce
// 扁平化数组
let arr = [1,[2,[3,4,5,[6,[7,8,9,10]]]]]
const iteration = (arr) => {
return arr.reduce((result,value) => Array.isArray(value) ? result.concat(iteration(value)) : result.concat(value),[])
}
console.log('iteration 之后的数据:',iteration(arr))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
步骤解析:
1: 使用reduce遍历数组
2: 判断当前的入参是不是数组,是的话,拼接函数返回值
3: 不是数组的话,直接拼接
使用while
// while
const iteration = (arr) => {
let result = []
while(arr.length !== 0){
console.log('arr:',arr)
console.log('arr.length:',arr.length)
let [first,...rest] = arr
if (Array.isArray(first)) {
// 第一项是数组,就解构
arr = [...first,...rest]
} else {
// 循环数据,把第一项不是数组的值添加到result中
// 把数组类型的值赋值给arr,依次循环,直到数组穷尽
result.push(first)
arr = [...rest]
}
}
return result
}
console.log("扁平化后的数组:",iteration(arr))
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
数组倒序
let arr:Array<number> = reactive([10,22,3,46,986,982,5,90,6])
const iteration = (arr:Array<number>):Array<number> =>{
if (arr.length == 0 || arr.length == 1) return arr
return [...iteration(arr.slice(1)),arr[0]]
}
console.log(iteration(arr))
步骤解析:
1:判断length为0或1的,直接返回原数组
2:return 取数组下标为1的值,传给函数本身,走第一步
3:使用扩展运算符把函数return的值进行拼接+下标为0的值
对象
对象属性遍历
let object1 = {
id:1,
value:'标题1',
obj:{
id:2,
value:'标题2',
obj:{
id:3,
value:'标题3',
obj:{
id:4,
value:'标题4',
obj:{
id:5,
value:'标题5',
obj:{
id:6,
value:'标题6',
},
},
},
},
},
}
interface Iobj {
id: number
value: string
}
interface Iobj1 {
obj:Iobj
}
const ergodic = (obj:Iobj1) => {
for(let k in obj) {
if (obj.hasOwnProperty(k)) {
if (typeof obj[k] == 'object') {
ergodic(obj[k])
} else {
console.log(`${k}:${obj[k]}`)
}
}
}
}
console.log('打印:',ergodic(object1))
步骤解析:
1:先循环对象
2:通过hasOwnProperty判断对象里面是否有属性
3: 通过typeof检查对象是不是对象
4:如果是对象再调用函数自身,重复前面1,2,3的步骤
5:如果不是对象,就打印数据
扁平化对象
const oldObject = {
"A": '1',
"B":{
"title": 'Hello world',
"tipes": 3,
"description":{
"title": 7,
"tipes":{
"title": 7,
"" : 2
}
}
},
"A1": 12,
}
const filterObj = (oldObject) => {
// 初始化一个新的对象,用来存储扁平化的数据
let newObject = {}
iteration(oldObject,newObject,'')
return newObject
function iteration (currentObject,newObject,privateKeyName) {
for (let key in currentObject){
let value = currentObject[key]
// 遍历对象,判断是不是对象,是对象就再次调用函数自身,不是就给newObject添加
if (value.constructor !== Object) {
if (privateKeyName == null || privateKeyName == '') {
newObject[key] = value
} else {
// 异常场景:当前的key可能为空字符串,就拿上级的privateKeyName作为新key
// 如果当前的key不为null或'',就做拼接
if (key === null || key === ''){
newObject[privateKeyName] = value
} else {
newObject[privateKeyName + '.' + key] = value
}
}
} else {
// key是个对象,判断上级的privateKeyName是否为null或空字符串
// 是的话,就把当前的key作成新的key
// 上级的privateKeyName不为null或空字符串,就做拼接给下个对象
if (privateKeyName === null || privateKeyName === '') {
iteration(value,newObject,key)
} else {
iteration(value,newObject,privateKeyName + '.' + key)
}
}
}
}
}
console.log(filterObj(oldObject))
// {
// "A": "1",
// "B.title": "Hello world",
// "B.tipes": 3,
// "B.description.title": 7,
// "B.description.tipes.title": 7,
// "B.description.tipes": 2,
// "A1": 12
// }
个人理解,递归的意思就是,在函数里面调用自身,前提是不满足函数之前的判断条件,才会进入再次调用函数本身的逻辑。