数组转树
interface IArrayItem {
id: number;
name: string;
parentId: number;
}
interface ITreeNode {
id: number;
name: string;
children?: ITreeNode[];
}
function covert(arr: IArrayItem[]): ITreeNode | null {
let root = null;
let map: Map<number, ITreeNode> = new Map();
arr.forEach(item => {
const { id, name, parentId } = item;
let treeNode = { id, name };
map.set(id, treeNode)
const parentNode = map.get(parentId);
if(parentNode){
if(parentNode.children === null) parentNode.children = [];
parentNode.children?.push(treeNode)
}
if(parentId === 0) root = treeNode
})
return root;
}
const arr = [
{ id: 1, name: '部门A', parentId: 0 },
{ id: 2, name: '部门B', parentId: 1 },
{ id: 3, name: '部门C', parentId: 1 },
{ id: 4, name: '部门D', parentId: 2 },
{ id: 5, name: '部门E', parentId: 2 },
{ id: 6, name: '部门F', parentId: 3 },
]
const tree = covert(arr)
console.info(tree)
并行请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
var urls = [1, 2, 3, 4, 5];
function multiRequest(urls = [], maxNum){
let len = urls.length;
let result = new Array(len).fill(1)
let count = 0;
return new Promise((resolve, reject) => {
if(count < maxNum){
next()
}
function next(){
let current = count++
if(current >= len){
resolve(result)
return;
}
const url = urls[current]
fetch(url).then(res => {
result[current] = res;
if(current < len){
next()
}
}, err => {
result[current] = err;
if(current < len){
next()
}
})
}
})
}
function multiRequest(urls = [], maxNum) {
const len = urls.length;
const result = new Array(len).fill(false);
let count = 0;
return new Promise((resolve, reject) => {
while (count < maxNum) {
next();
}
function next() {
let current = count++;
if (current >= len) {
resolve(result);
return;
}
const url = urls[current];
console.log(`开始 ${current}`, new Date().toLocaleString());
fetch(url)
.then((res) => {
result[current] = res;
console.log(`完成 ${current}`, new Date().toLocaleString());
if (current < len) {
next();
}
})
.catch((err) => {
console.log(`结束 ${current}`, new Date().toLocaleString());
result[current] = err;
if (current < len) {
next();
}
});
}
});
}
console.log(multiRequest(urls, 2));
</script>
</body>
</html>
深度打平
function flattenDeep(arr: any[]): any[]{
let res: any[] = []
arr.forEach(item => {
if(Array.isArray(item)){
const flatItem = flattenDeep(item)
flatItem.forEach(n => res.push(n))
}else{
res.push(item)
}
})
return res
}
function flattenDeep2(arr: any[]): any[]{
let res : any[]= []
arr.forEach(item => {
if(Array.isArray(item)){
const flatItem = flattenDeep2(item)
flatItem.forEach(n => res.push(n))
}else{
res.push(item)
}
})
return res
}
判断类型
function getType(x: any): string{
const originType = Object.prototype.toString.call(x);
const spaceIndex = originType.indexOf(' ');
const type = originType.slice(spaceIndex+1, -1);
return type.toLowercase();
}
new
function customNew<T>(constructor: Function,...args: any[]): T{
const obj = Object.create(constructor.prototype);
constructor.apply(obj,args)
return obj;
}
instanceof
function myInstanceof(instance: any, origin: any): boolean{
if(instance === null) return false;
const type = typeof instance;
if(type !== 'object' && type !== 'function') return false;
let tempInstance = instance;
while(tempInstance){
if(tempInstance.__proto__ === origin.prototype){
return true;
}
tempInstance = tempInstance.__proto__
}
return false;
}
bind
Function.prototype.customBind = function(context: any, ...bindArgs: any[]){
const self = this;
return function(...args: any[]){
const newArgs = bindArgs.concat(args)
return self.apply(context, newArgs)
}
}
深克隆
function cloneDeep(obj: any){
if(typeof obj !== 'object' || obj === null) return obj;
let res: any;
if(obj instanceof Array){
res = []
}else {
res = {};
}
for(let key in obj){
if(obj.hasOwnProperty(key)){
res[key] = cloneDeep(obj[key])
}
}
return res;
}
function cloneDeep2(obj: any, map = new WeakMap()):any{
if(typeof obj !== 'object' || obj === null) return obj;
const objFromMap = map.get(obj)
if(objFromMap) return objFromMap;
let target: any = {};
map.set(obj, target)
if(obj instanceof Array){
target = obj.map(item => cloneDeep2(item, map))
}
for(const key in obj){
const val = obj[key];
const val1 = cloneDeep2(val, map)
target[key] = val1
}
if(obj instanceof Map){
target = new Map()
obj.forEach((v,k) => {
const v1 = cloneDeep2(v,map)
const k1 = cloneDeep2(k,map)
target.set(k1,v1)
})
}
if(obj instanceof Set){
target = new Set()
obj.forEach(v =>{
const v1 = cloneDeep2(v,map)
target.add(v1)
})
}
return target;
}
大数之和
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
let a = '9007199254740991'
let b = '1234567899999999999'
function add(a, b) {
let maxLen = Math.max(a.length, b.length)
a = a.padStart(maxLen, 0)
b = b.padStart(maxLen, 0)
let t = 0
let f = 0
let sum = ''
for (let i = maxLen - 1
t = parseInt(a[i]) + parseInt(b[i]) + f
f = Math.floor(t / 10)
sum = (t % 10) + sum
}
if (f == 1) {
sum = '1' + sum
}
return sum
}
function toThousands(num) {
var result = [],
counter = 0
num = (num || 0).toString().split('')
console.log('ddd', num)
for (var i = num.length - 1
counter++
result.unshift(num[i])
console.log('eee', result)
if (!(counter % 3) && i != 0) {
result.unshift(',')
}
console.log('fff', result)
}
return result.join('')
}
console.log(add(a, b))
console.log(Number(add(a, b)))
console.log(Number(add(a, b)).toLocaleString())
console.log(toThousands(Number(add(a, b))))
</script>
</body>
</html>
event
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class EventEmitter{
constructor(){
this.listeners = {};
}
on(type, cb){
if(!this.listeners[type]){
this.listeners[type] = []
}
this.listeners[type].push(cb)
}
emit(type, ...args){
if(this.listeners[type]){
this.listeners[type].forEach(cb => {
cb(...args)
})
}
}
off(type,cb){
if(this.listeners[type]){
const targetIndex = this.listeners[type].findIndex(item => item ===cb)
if(targetIndex !== -1){
this.listeners[type].splice(targetIndex,1)
}
if(this.listeners[type].length === 0){
delete this.listeners[type]
}
}
}
once(type, cb){
function newCb(...args){
cb(...args)
this.off(type, newCb)
}
this.on(type, newCb)
}
offAll(type){
if(this.listeners[type]){
delete this.listeners[type]
}
}
}
</script>
</body>
</html>
观察者模式
class Subject {
constructor() {
this.observerList = [];
}
addObserver(observer) {
this.observerList.push(observer);
}
removeObserver(observer) {
const index = this.observerList.findIndex(o => o.name === observer.name);
this.observerList.splice(index, 1);
}
notifyObservers(message) {
const observers = this.observerList;
observers.forEach(observer => observer.notified(message));
}
}
class Observer {
constructor(name, subject) {
this.name = name;
if (subject) {
subject.addObserver(this);
}
}
notified(message) {
console.log(this.name, 'got message', message);
}
}
function main() {
const subject = new Subject();
const observerA = new Observer('observerA', subject);
const observerB = new Observer('observerB', subject);
subject.notifyObservers(`Hello from subject at ${new Date()}`);
console.log('------------------------')
setTimeout(() => {
const observerC = new Observer('observerC');
const observerD = new Observer('observerD');
subject.addObserver(observerC);
subject.addObserver(observerD);
subject.notifyObservers(`Hello from subject at ${new Date()}`);
console.log('------------------------')
}, 1000)
setTimeout(() => {
subject.removeObserver(observerA);
subject.notifyObservers(`Hello from subject at ${new Date()}`);
console.log('------------------------')
}, 2000)
}
main();
PROMISE
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function promiseAll3(promises){
if(!Array.isArray(promises)){
throw new Error('promises must is Array')
}
return new Promise((resolve, reject) => {
let promiseLen = promises.length;
let resolvedNum = 0;
let resultValue = new Array(promiseLen);
for(let i = 0 ;i<promiseLen;i++){
(function(i){
Promise.then(res => {
resultValue[i]= res;
resolvedNum++
if(resolvedNum === promiseLen){
resolve(resultValue)
}
}, err => {
reject(err)
})
})(i)
}
})
}
function promiseAll(promises){
if(!Array.isArray(promises)){
throw new Error('promises 必须是 数组')
}
return new Promise((resolve, reject) => {
let promisesLen = promises.length;
let resolvedNum = 0;
let resolvedValue = new Array(promisesLen)
for(let i = 0;i<promisesLen;i++){
(function(i){
Promise.resolve(promises[i]).then(res => {
resolvedNum++
resolvedValue[i] = res;
if(resolvedNum === promisesLen){
return resolve(resolvedValue)
}
}, err => {
return reject(err)
})
})(i)
}
})
}
function promiseRace(promises){
if(!Array.isArray(promises)){
throw new Error('promises 必须是 数组')
}
return new Promise((resolve, reject) => {
for(let i = 0;i<promises.length;i++){
Promise.resolve(promises[i]).then(res =>{
resolve(res)
}, err => {
reject(err)
})
}
})
}
</script>
</body>
</html>