尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
手写核心工具库:防抖节流、发布订阅、Promise、简易路由、简易 Vue 响应式
Hi我是前端人类学无论前端框架如何更迭防抖节流、发布订阅、Promise、路由、响应式这五个核心模块始终是支撑应用的基石。手写它们不仅能深入理解底层原理更能提升代码设计能力。本文将逐一实现并剖析其核心逻辑。文章目录一、防抖Debounce与节流Throttle1.1 防抖Debounce连续触发只执行最后一次1.2 节流Throttle固定时间间隔执行一次二、发布订阅Event Bus三、PromiseA 规范核心实现四、简易路由Hash 模式五、简易 Vue 响应式2.x 核心六、总结一、防抖Debounce与节流Throttle两者都是频率控制函数用于限制函数执行次数但适用场景截然不同。1.1 防抖Debounce连续触发只执行最后一次原理每次触发都重置定时器确保仅在停止触发后的等待时间结束后执行一次。functiondebounce(fn,delay300){lettimernull;returnfunction(...args){clearTimeout(timer);timersetTimeout((){fn.apply(this,args);},delay);};}适用场景输入框搜索联想、窗口 resize 计算。1.2 节流Throttle固定时间间隔执行一次原理通过时间戳或定时器控制在时间窗口内最多执行一次。functionthrottle(fn,interval300){letlastTime0;returnfunction(...args){constnowDate.now();if(now-lastTimeinterval){lastTimenow;fn.apply(this,args);}};}适用场景滚动加载、按钮高频点击防止重复提交。二、发布订阅Event Bus发布订阅模式是观察者模式的一种实现核心是事件中心订阅者on注册事件发布者emit触发事件同时支持移除off和一次性订阅once。classEventBus{constructor(){this.events{};}// 订阅on(name,callback){if(!this.events[name]){this.events[name][];}this.events[name].push(callback);}// 取消订阅off(name,callback){if(!this.events[name])return;if(!callback){deletethis.events[name];return;}this.events[name]this.events[name].filter(cbcb!callback);}// 触发emit(name,...args){if(!this.events[name])return;this.events[name].forEach(cbcb(...args));}// 一次性订阅once(name,callback){constwrapper(...args){callback(...args);this.off(name,wrapper);};this.on(name,wrapper);}}三、PromiseA 规范核心实现手写 Promise 的关键是理解状态流转pending → fulfilled / rejected和链式调用。核心骨架constPENDINGpending;constFULFILLEDfulfilled;constREJECTEDrejected;classMyPromise{constructor(executor){this.statePENDING;this.valueundefined;this.reasonundefined;this.onFulfilledCallbacks[];this.onRejectedCallbacks[];constresolve(value){if(this.statePENDING){this.stateFULFILLED;this.valuevalue;this.onFulfilledCallbacks.forEach(fnfn());}};constreject(reason){if(this.statePENDING){this.stateREJECTED;this.reasonreason;this.onRejectedCallbacks.forEach(fnfn());}};try{executor(resolve,reject);}catch(err){reject(err);}}then(onFulfilled,onRejected){onFulfilledtypeofonFulfilledfunction?onFulfilled:vv;onRejectedtypeofonRejectedfunction?onRejected:err{throwerr;};constpromise2newMyPromise((resolve,reject){if(this.stateFULFILLED){setTimeout((){try{constxonFulfilled(this.value);this.resolvePromise(promise2,x,resolve,reject);}catch(err){reject(err);}});}if(this.stateREJECTED){setTimeout((){try{constxonRejected(this.reason);this.resolvePromise(promise2,x,resolve,reject);}catch(err){reject(err);}});}if(this.statePENDING){this.onFulfilledCallbacks.push((){setTimeout((){try{constxonFulfilled(this.value);this.resolvePromise(promise2,x,resolve,reject);}catch(err){reject(err);}});});this.onRejectedCallbacks.push((){setTimeout((){try{constxonRejected(this.reason);this.resolvePromise(promise2,x,resolve,reject);}catch(err){reject(err);}});});}});returnpromise2;}// 核心解析处理 then 返回值的穿透和链式resolvePromise(promise2,x,resolve,reject){if(promise2x){returnreject(newTypeError(Chaining cycle detected));}if(x(typeofxobject||typeofxfunction)){letcalledfalse;try{constthenx.then;if(typeofthenfunction){then.call(x,y{if(called)return;calledtrue;this.resolvePromise(promise2,y,resolve,reject);},r{if(called)return;calledtrue;reject(r);});}else{resolve(x);}}catch(err){if(called)return;calledtrue;reject(err);}}else{resolve(x);}}// 静态方法staticresolve(value){returnnewMyPromise(resolveresolve(value));}staticreject(reason){returnnewMyPromise((_,reject)reject(reason));}// catch 是 then 的语法糖catch(onRejected){returnthis.then(null,onRejected);}}四、简易路由Hash 模式前端路由的核心是监听 URL 变化渲染对应组件。Hash 模式利用window.location.hash和hashchange事件实现。classRouter{constructor(){this.routes{};this.currentPath;// 监听 hash 变化window.addEventListener(hashchange,this.updateView.bind(this));// 页面加载时也要触发window.addEventListener(load,this.updateView.bind(this));}// 注册路由route(path,callback){this.routes[path]callback;}// 更新视图updateView(){constpathwindow.location.hash.slice(1)||/;this.currentPathpath;constcallbackthis.routes[path];if(callback){callback();}}// 跳转push(path){window.location.hashpath;}// 获取当前路径getCurrentPath(){returnthis.currentPath;}}// 使用示例constrouternewRouter();router.route(/,()console.log(首页));router.route(/about,()console.log(关于));router.push(/about);// 触发 about 路由五、简易 Vue 响应式2.x 核心Vue 2 的响应式核心是Object.defineProperty劫持数据结合发布订阅模式通知视图更新。核心三要素Observer、Dep、Watcher// 1. Dep依赖收集器发布订阅classDep{constructor(){this.subscribers[];}addSub(watcher){this.subscribers.push(watcher);}notify(){this.subscribers.forEach(watcherwatcher.update());}}// 2. Observer递归劫持所有属性functionobserve(obj){if(!obj||typeofobj!object)return;Object.keys(obj).forEach(keydefineReactive(obj,key,obj[key]));}functiondefineReactive(obj,key,val){constdepnewDep();// 深度劫持observe(val);Object.defineProperty(obj,key,{get(){// 依赖收集将当前 Watcher 添加到 depif(Dep.target){dep.addSub(Dep.target);}returnval;},set(newVal){if(newValval)return;valnewVal;observe(newVal);// 新值也需要劫持dep.notify();// 触发更新}});}// 3. Watcher观察者负责更新视图classWatcher{constructor(vm,key,callback){this.vmvm;this.keykey;this.callbackcallback;// 把当前 Watcher 挂到 Dep.target触发 getter 完成依赖收集Dep.targetthis;this.valuevm[key];// 读取触发 getterDep.targetnull;}update(){constnewValuethis.vm[this.key];if(newValue!this.value){this.valuenewValue;this.callback(newValue);}}}// 4. 简易 Vue 类classMiniVue{constructor(data){this._datadata;observe(data);}// 注册 Watcher$watch(key,callback){newWatcher(this,key,callback);}}// 使用示例constvmnewMiniVue({name:张三,age:18});vm.$watch(name,(newVal){console.log(姓名变了:,newVal);});vm._data.name李四;// 触发更新六、总结模块核心思想关键API/技术防抖延迟执行重置定时器setTimeoutclearTimeout节流时间窗口内只执行一次时间戳 / 定时器控制发布订阅事件中心管理回调on/emit/off/oncePromise状态机 链式调用resolve/reject/then路由(Hash)监听 hashchange 渲染组件window.location.hashVue响应式数据劫持 发布订阅Object.definePropertyDep/Watcher手写这些工具库本质上是理解设计模式观察者、发布订阅、代理和底层 APIdefineProperty、Proxy、Promise的过程。无论框架如何演变这些核心思想将始终伴随前端开发。
RELATED

相关推荐

Linux运维实战:从零部署Web应用到Docker容器化完整指南

Linux运维实战:从零部署Web应用到Docker容器化完整指南

如果你是一名刚入行的运维工程师,或者想从开发转向运维,面对Linux服务器上密密麻麻的命令行,是不是经常感到无从下手?网上教程要么太零散,要么一上来就讲高深原理,真正能让你从“双击安装”到“独立部署服务”的完整路径少之又少。 这篇文章要解决的,就是这个问题。我们…

📅 2026/8/23 2:29:47
文档下载革命:从“看得见“到“拿得到“的35+平台终极解决方案

文档下载革命:从“看得见“到“拿得到“的35+平台终极解决方案

文档下载革命:从"看得见"到"拿得到"的35平台终极解决方案 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档&…

📅 2026/8/23 2:30:03
DeepSeek-V4技术解析:AI编程助手的突破与应用

DeepSeek-V4技术解析:AI编程助手的突破与应用

1. DeepSeek-V4技术解析:重新定义AI编程边界 当我在本地测试环境首次运行DeepSeek-V4的代码生成模块时,其响应速度和对复杂业务逻辑的理解能力确实让我这个有十年全栈开发经验的老手感到惊艳。与当前主流GPT系列相比,这个新一代AI编程助手在三…

📅 2026/9/10 11:16:01
MORE NEWS

更多资讯

📰

OneUptime 集成 Discord:用内置工作流组件将事故通知推送到频道

OneUptime 集成 Discord:用内置工作流组件将事故通知推送到频道 【免费下载链接】oneuptime Complete open-source monitoring and observability platform. 项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime 导读 本指南讲解如何在 OneUptime …

📰

Qt 5.14.2 ARM交叉编译踩坑全记录:从工具链到上板部署

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

CANN opbase 算子开发指南:IsComplexType 复数数据类型判断接口详解

CANN opbase 算子开发指南:IsComplexType 复数数据类型判断接口详解 【免费下载链接】opbase 本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。 项目地址: https://gitcode.com/cann/opbase 导读 IsComplexType 是 CANN …

📰

Unity视频播放插件AVPro Video免费版与收费版选型指南

在Unity项目里做视频播放,绕不开的一个插件就是AVPro Video。我最早接触它是在一个展厅互动项目上,当时用Unity自带的VideoPlayer播放4K宣传片,在PC上跑得好好的,一打包到安卓一体机就各种卡顿、音画不同步,折腾了整整…

📰

Hugo 菜单遍历方法全解析:ByName、ByWeight、Limit、Reverse 实战指南

Hugo 菜单遍历方法全解析:ByName、ByWeight、Limit、Reverse 实战指南 【免费下载链接】hugo The world’s fastest framework for building websites. 项目地址: https://gitcode.com/gh_mirrors/hu/hugo Hugo 的 Menu 类型提供了一组用于遍历菜单条目&…

📰

医院在线预约系统课程设计全流程:从数据流图到测试方案

简介:适合软件工程课程设计使用的医院在线预约系统完整报告,面向计算机相关专业学生及需要完成类似课题的开发者,用于理解需求分析、结构化设计与面向对象设计的全流程。资源为一份 Word 文档,压缩包内共 1 个 doc 文件&#xff0…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬