*多个实现异步的方法
- Promise.all(iterable)实现,同步执行完所有参数里的promise任务,再继续执行then的异步任务
// promise.all同步任务
const promiseMain = (index) => {
return new Promise((resolve,reject)=>{
setTimeout(() => {
resolve(index)
console.log('同步promise.all',index, new Date());
}, 500);
})
}
// 生成全部异步操作
const task = []
for (let i=0;i<4;i++) {
task.push(promiseMain(i))
}
// 同步执行完异步操作后输出done
Promise.all(task).then(r=> console.log("all task done!",r));
- reduce实现异步,在上个请求执行后 按顺序执行代码 而不会一下子执行全部请求
task.reduce((pre,curr)=>{
return pre.then((r)=> {
return new Promise((resolve, reject) => {
setTimeout(async () => {
console.log('异步',await curr, new Date())
resolve()
}, 1000)
})
})
},Promise.resolve())
- for循环实现多个异步方法
for (let i =0; i<task.length;i++ ) {
(function(j){
setTimeout(async() => {
console.log('异步',await task[j], new Date())
}, 1000*j)
})(i) // 立即调用绑定当前索引
}
image.png
*数组去重
- new Set去重,new set之后是一个类数组
let arr = [1,2,3,5,3,4,4,1]
// 可以...扩展运算符解构
arr = [...new Set(arr)] // [1,2,3,5,4]
// 或者用Array.from从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组
Array.from(new Set(arr)) // [1,2,3,5,4]
- reduce 去重
let arr = [1,2,3,5,3,4,4,1]
arr = arr.reduce((pre,curr)=> pre.concat(pre.includes(curr)?[]:curr),[])
// [1,2,3,5,4]
*使定时器没有回调,不需要处理任务,只需要等“一秒”,类似于sleep
const delay = (time) => {
return new Promise((resolve) => {setTimeout(resolve, time);})
}
console.log(111);
await delay(1000);
console.log(333);
image.png
*组合数组,两个数组交叉合并
let arr = [1,3,5,7];
let arr2 = [2,4,6,8,9];
const compose = (arr,arr2) => {
if (!Array.isArray(arr) || !Array.isArray(arr2)) return;
let newArr = []
const minLength = Math.min(arr.length,arr2.length);
for (let i=0;i<minLength;i++) {
newArr.push(arr[i]);
newArr.push(arr2[i]);
}
newArr = arr.length>arr2.length ? newArr.concat(arr.slice(minLength)):newArr.concat(arr2.slice(minLength));
return newArr
}
compose(arr,arr2); // [1,2,3,4,5,6,7,8,9]
*写个方法实现a的幂次方, 传入两个值a ,b, b代表几次幂,求a的幂次方结果。
function getAdd(a, b) {
let abs = Math.abs(b); // 取b的正整数
let result = 1;
for (let i = 0; i < abs; i++) {
result *= a;
}
if (b < 0) {
result = 1 / result;
}
return result
}
image.png
*拍平一个数组,并求和。
const arr = [8, 12,4,[5, 9, 4], 1, 3, [7, 5, 10, [3, 4, 6, 2]], 4, 3, 2, 4];
function minArr(arr) {
if (!Array.isArray(arr)) return;
const a= arr.reduce((init,curr) => Array.isArray(curr)?init.concat(minArr(curr)):init.concat(curr),[]);
return a
}
console.log(minArr(arr)) // 拍平数组后
const sum = minArr(arr).reduce((init,curr)=>init+curr,0);
console.log(sum)
image.png
*防抖函数
- 所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
- 也直接引用import { debounce } from 'lodash';
const dounce = (fn,time) => {
let timeOut;
let that = this;
return function () {
if (timeOut) clearTimeout(timeOut);
timeOut = setTimeout(() => {
fn.apply(that,arguments)
}, time);
}
}
用防抖函数监听浏览器窗口变化
window.addEventListener('resize', debounce((event)=>{
console.log(event)
},500))
*节流函数
- 所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
const throttle = (func, time) => {
let canDo = true;
let that = this;
return function() {
if (!canDo) return;
canDo = false;
setTimeout(() => {
func.apply(that.arguments)
canDo = true
}, time);
}
}
*函数柯里化求和
const sum = (...arg) => {
let x = arg.reduce((init,curr)=>init+curr);
return function (...arg2) {
if (arg2.length === 0) return x;
let y = arg2.reduce((init,curr)=>init+curr);
return sum(x+y)
}
}
console.log(sum(1,2,2,5)(7)()) // 17
*实现 bind ()
Function.prototype.MyBind = function (context, ...args) {
let self = this;
return function() {
return self.apply(context, args);
}
}
// test
let a = {name: 'jack'}
let test = function() {
console.log(this.name); // jack
}
let rs = test.MyBind(a);
rs();
*实现深拷贝
- 常用方法JSON.parse(JSON.stringify())
- 使用lodash 的深拷贝函数。
- 手写deepClone
const deepClone = (obj) => {
// 通过从原型上判断对象还是数组
const copy = obj instanceof Array ? []:{};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// obj[key] 是否是对象,如果是对象,递归遍历
copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
}
}
return copy
}
let b = {name: 'jack', birth: {year: '1997', month: '10'}}
let c = deepClone(b);
b.name = 'nacy';
// b 的name变了,但c还是原来的name
// b.name: nacy ----c.name: jack
*二维数组转树形结构数组
let arr = [
{
"id": "01",
"name": "公司",
},
{
"id": "02",
"parentId": "01",
"name": "一级部门",
},
{
"id": "30",
"parentId": "02",
"name": "二级部门",
},
{
"id": "31",
"parentId": "02",
"name": "二级部门",
},
{
"id": "40",
"parentId": "30",
"name": "三级部门",
},
{
"id": "41",
"parentId": "30",
"name": "三级部门",
}
];
function getTree(arr) {
if (!Array.isArray(arr)) return;
const parents = arr.filter(f=>!f.parentId);
const children = arr.filter(c=>c.parentId !== undefined && c.parentId !== null);
//定义转换方法的具体实现
let translator = (parents, children) => {
//遍历父节点数据
parents.forEach((parent) => {
//遍历子节点数据
children.forEach((current, index) => {
//此时找到父节点对应的一个子节点
if (current.parentId === parent.id) {
//对子节点数据进行深拷贝,不影响原数据
let temp = JSON.parse(JSON.stringify(children))
//让当前子节点从temp中移除,temp作为新的子节点数据,这里是为了让递归时,子节点的遍历次数更少,如果父子关系的层级越多,越有利
temp.splice(index, 1)
//把找到子节点放入父节点的children属性中
typeof parent.children !== 'undefined' ? parent.children.push(current) : parent.children = [current];
//让当前子节点作为唯一的父节点,去递归查找其对应的子节点
translator([current], temp)
}
}
)
}
)
}
//调用转换方法
translator(parents, children)
//返回最终的结果
return parents
}
getTree(arr)
网友评论