apply
function myApply(obj,args){
obj = (obj===null || obj === undefined) ? window:Object(obj)
obj.fn = this
obj.fn(...args)
delete obj.fn
}
Function.prototype.myApply = myApply
call
Function.prototype.myCall = function(obj,...args){
obj = (obj===null || obj === undefined) ? window:Object(obj)
obj.fn = this
obj.fn(...args)
delete obj.fn
}
bind
Function.prototype.myBind = function(obj,...args){
obj = obj ===null||obj ===undefined ? window:Object(obj)
obj.fn = this
return (...fnArgs)=>{
obj.fn(...args,...fnArgs)
}
}
new
function myNew(fn){
if (typeof fn !== 'function') {
throw 'must be a function'
}
var obj = Object.create(fn.prototype)
var args = [...arguments].slice(1)
var result = fn.apply(obj,args)
if ((typeof result ==='object' && typeof result !== null) || typeof result ==='function') {
return result
}
return obj
}
防抖函数
function debounce(fn, wait = 500, immediate = true) {
let timer = null
let isInvoke = false
const _debounce = function (...args) {
if (timer) clearTimeout(timer)
if (immediate && !isInvoke) {
fn.apply(this, args)
isInvoke = true
return
}
timer = setTimeout(() => {
fn.apply(this, args)
timer = null
isInvoke = false
}, wait)
}
_debounce.cancle = function(){
if (timer) clearTimeout(timer)
timer = null
isInvoke = false
}
return _debounce
}
const inp = document.querySelector('input')
inp.oninput = debounce(function (event) {
console.log(this.value)
}, 1000)
节流函数
function throttle(fn, interval, immediate = true, trailing = false) {
let startTime = 0
let timer = null
let res = null
const _throttle = function (...args) {
return new Promise((resolve, reject) => {
try {
let endTime = new Date().getTime()
if (!immediate && startTime === 0) {
startTime = endTime
}
let wait = interval - (endTime - startTime)
if (wait <= 0) {
if (timer) clearTimeout(timer)
res = fn.apply(this, args)
resolve(res)
startTime = endTime
timer = null
return
}
if (trailing && !timer) {
timer = setTimeout(() => {
res = fn.apply(this, args)
resolve(res)
startTime = new Date().getTime()
timer = null
}, wait)
}
} catch (error) {
reject(error)
}
})
}
_throttle.cancel = function () {
if (timer) clearTimeout(timer)
timer = null
startTime = 0
}
return _throttle
}
const inp = document.querySelector('input')
inp.oninput = throttle(function () {
console.log(this.value)
}, 1000)
深拷贝
1. JSON方法:JSON.parse(JSON.stringify(obj)) 创建出一个全新的对象
缺点:
1.1 对一些数据无力,如:函数、Symbol
1.2 如果存在对象的循环引用,会报错
function isObject(value){
const valueType = typeof value
return (value !== null) && (value === 'object' || value === 'function')
}
function deepCopy(obj,map=new weakMap()){
if (typeof obj === 'symbol') {
return Symbol(obj.description)
}
if (!isObject(obj)) {
return obj
}
if (obj instanceof Set) {
const newSet = new Set()
for (let item of obj) {
newSet.add(item)
}
return newSet
}
if (obj instanceof Map) {
return new Map(obj)
}
if (map.get(obj)) {
return map.get(obj)
}
const newObj = Array.isArray(obj)?[]:{}
map.set(obj,newObj)
for (const key in obj) {
newObj[key] = deepCopy(obj[key],map)
}
let objSymbols = Object.getOwnpropertySymbols(obj)
for (const key of objSymbols) {
objSymbols[key.description] = deepCopy(obj[key],map)
}
return newObj
}
事件总线
event-bus: 跨文件、跨组件通信
class EventBus {
constructor(){
this.eventObj = {}
}
on(eventName,eventFn){
let eventFns = this.eventObj[eventName]
if (!eventFns) {
this.eventObj[eventName] = []
}
eventFns.push(eventFn)
}
off(eventName,eventFn){
let eventFns = this.eventObj[eventName]
if (!eventFns) {
Reflect.delete(this.eventObj,eventName)
return
}
for (let i=0;i<eventFns.length;i++){
const fn = eventFns[i]
if (fn === eventFn) {
eventFns.splice(i,1)
break
}
}
}
emit(eventName,...args){
const eventFns = this.eventObj[eventName]
if (!eventFns) return
for (let fn in eventFns) {
fn(...args)
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署