//数组扁平-------------------------------------------------------------------------------------------------------------------------------
const flat = (arr, depth = Infinity) => arr.reduce((total, cur) => {
if(depth > 0 && Array.isArray(cur)){
let flattened = flat(cur, depth - 1)
return [...total, ...flattened]
}
else return [...total, cur]
}, [])
console.log(flat([1,[2,[3,4,[6]]],7,[8,[10]]], 1))
new URL
// url字符串解析-----------------------------------------------------------------------------------------------------------
const urlString = "https://www.example.com:8080/search?query=JavaScript&page=1#results";
const regex = /^(\w+):\/\/([^/:]+)(?::(\d+))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/;
const reg = /([a-z]+):\/\/([a-zA-Z0-9\.]+):?(\d+)?(.+(?=\?))\?([^#]*)#?(.*)/;
// 使用正则表达式匹配 URL 字符串,并提取各个部分
const matches = urlString.match(reg);
console.log(matches)
const [, protocol, hostname, port, pathname, search, hash] = matches;
// 获取查询参数
const queryParams = {};
search.replace(/([^=&]+)=([^&]*)/g, (match, key, value) => {
queryParams[key] = decodeURIComponent(value);
});
console.log(protocol); // 输出:https
console.log(hostname); // 输出:www.example.com
console.log(port); // 输出:8080
console.log(pathname); // 输出:/search
console.log(search); // 输出:?query=JavaScript&page=1
console.log(hash); // 输出:#results
console.log(queryParams); // 输出:{query: "JavaScript", page: "1"}
//简单实现一个事件订阅机制,具有监听on和触发emit以及取消监听off方法------------------------------------------------------------------
class EventListen{
constructor() {
this.deps = {}
}
on(callback, eventName){
if(!this.deps[eventName]){
this.deps[eventName] = []
}
this.deps[eventName].push(callback)
}
emit(eventName, ...args){
const callbacks = this.deps[eventName]
if(callbacks){
callbacks.forEach((callback) => {
callback.apply(this, args)
})
}
}
//只订阅一次
once(callback, eventName) {
const onceCb = (...args) => {
callback(...args);
this.off(eventName, onceCb)
}
this.on(callback, onceCb)
}
off(eventName, callback){
const callbacks = this.deps[eventName]
if(callbacks){
const index = callbacks.indexOf(callback)
if(index >= 0){
callbacks.splice(index,1)
}
}
}
}
//简单实现一个promise.all---------------------------------------------------------------------------
function myAll(promiseList) {
return new Promise((resolve, reject) => {
let res = []
promiseList.forEach((promise, index) => {
Promise.resolve(promise).then(o => {
res.push(o)
if(index === promiseList.length - 1) resolve(res)
}).catch(e => {
reject(e)
})
})
})
}
//简单实现一个深拷贝---------------------------------------------------------------------------
const deepClone = (obj)=> {
const set = new WeakSet()
set.add(obj)
const copy = (obj) => {
if(!obj || typeof obj !== 'object') return obj //基本数据类型
const newObj = Array.isArray(obj) ? [] : {}
for(let key in obj){
let val = obj[key]
if(typeof val != 'object'){
newObj[key] = val
}else{
if(set.has(val)){
newObj[key] = null
}else {
set.add(val)
newObj[key] = copy(val)
}
}
}
return newObj
}
return copy(obj)
}
const seven = {
name: 'seven'
}
const juejin = {
name: 'juejin',
relative: seven
}
seven.relative = juejin
const newObj = deepClone(seven)
console.log(newObj)
//时间戳格式化---------------------------------------------------------------------------
function format(formatStr, timeStamp){
timeStamp = new Date(timeStamp)
const objs = {
'Y+': timeStamp.getFullYear(),
'M+': timeStamp.getMonth()+1,
'd+': timeStamp.getDate(),
'h+': timeStamp.getHours(),
'm+': timeStamp.getMinutes(),
's+': timeStamp.getSeconds()
}
for(let obj in objs){
const reg = new RegExp(obj)
if(reg.test(formatStr)){
const value = objs[obj] + ''
formatStr = formatStr.replace(reg, value)
}
}
return formatStr
}
console.log(format('YY/MM/dd/hh:mm:ss',1659252290626))
//手写instanceof---------------------------------------------------------------------------
function myInstanceOf(instance, parent){
if(!instance?._proto_ || ! parent.prototype) return false
if(instance._proto_ === parent.prototype) return true
return myInstanceOf(instance, parent.prototype)
}
//实现一个compose---------------------------------------------------------------------------
const compose = (...fns) =>
// 注意 f、g 的位置,如果实现从左到右计算,则置换顺序
fns.reduce((f, g) => (...args) => f(g(...args)))
//实现一个curry---------------------------------------------------------------------------
const curry = (fn, ...args1) => {
let _length = fn.length
return (...args2)=> { //继续接收剩余参数
let newArgs = [...args1, ...args2]
if(newArgs.length >= _length) return fn(...newArgs)
else return curry(fn, ...newArgs)
}
}
const add = (x, y, z ,m) => x+y+z+m
let _add = curry(add,3)
console.log(_add(1,2)(4))
//数组转树---------------------------------------------------------------------------------------------------
let input = [
{ pid: 0, id: 1, name: "中国" },
{ pid: 1, id: 2, name: "广东" },
{ pid: 2, id: 3, name: "深圳" },
{ pid: 3, id: 6, name: "福田" },
{ pid: 1, id: 4, name: "香港" },
{ pid: 4, id: 5, name: "九龙" },
];
const arrayToTree = (arr) => {
let map = {}
for(let key of arr){
map[key.id] = key
}
let res = []
for(let key in arr){
const node = arr[key]
if(map[node.pid]){
map[node.pid].children ? map[node.pid].children.push(node) : map[node.pid].children = [node]
}else{
res.push(node)
}
Reflect.deleteProperty(node, 'pid')
}
return res
}
const tree = arrayToTree(input)
console.log(tree)
//lodash.get---------------------------------------------------------------------------------------------------
function get (source, path, defaultValue = undefined) {
// a[3].b -> a.3.b
const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.')
let result = source
for (const p of paths) {
result = Object(result)[p]
if (result === undefined) {
return defaultValue
}
}
return result
}
console.log(get( { a: [{ b: 1 }]}, 'a[0].b'))
//promise重试---------------------------------------------------------------------------
function retry(getData, times, delay) {
return new Promise((resolve, reject) => {
function attempt() {
getData.then(resolve).catch((err) => {
console.log(`还有${times}次机会`)
if(times == 0) {
reject(err)
} else {
times--
setTimeout(attempt(), delay)
}
})
}
attempt()
})
}
//new----------------------------------------------------------------------------------------------------------------------------------
function _new(obj, ...rest){
// 基于obj的原型创建一个新的对象
const newObj = Object.create(obj.prototype);
// 添加属性到新创建的newObj上, 并获取obj函数执行的结果.
const result = obj.apply(newObj, rest);
// 如果执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象
return typeof result === 'object' ? result : newObj;
}
class Scheduler {
constructor() {
this.tasks = [], // 待运行的任务
this.usingTask = [] // 正在运行的任务
}
// promiseCreator 是一个异步函数,return Promise
add(promiseCreator) {
return new Promise((resolve, reject) => {
promiseCreator.resolve = resolve
if (this.usingTask.length < 2) {
this.usingRun(promiseCreator)
} else {
this.tasks.push(promiseCreator)
}
})
}
usingRun(promiseCreator) {
this.usingTask.push(promiseCreator)
promiseCreator().then(() => {
promiseCreator.resolve()
let index = this.usingTask.findIndex(promiseCreator)
this.usingTask.splice(index, 1)
if (this.tasks.length > 0) {
this.usingRun(this.tasks.shift())
}
})
}
}
const timeout = (time) => new Promise(resolve => {
setTimeout(resolve, time)
})
const scheduler = new Scheduler()
const addTask = (time, order) => {
scheduler.add(() => timeout(time)).then(() => console.log(order))
}
addTask(400, 4)
addTask(200, 2)
addTask(300, 3)
addTask(100, 1)
//vue倒计时---------------------------------------------------------------------------https://juejin.cn/post/6882650885399248904#heading-0
前端常见手撕
于 2023-08-15 23:30:33 首次发布