当前位置: 首页 > news >正文

【总结】手写实现JS常见核心的概念

文章目录

        • 1.函数防抖和函数节流
        • 2.对象深拷贝
        • 3.数组去重
        • 4.apply,call和bind方法
        • 5.new操作符
        • 6.instanceof()方法
1.函数防抖和函数节流

函数防抖和节流都是通过限制事件的触发频率来进行性能优化,常见场景有鼠标拖拽,窗口移动等,其中,
函数防抖的原理是:触发事件的n秒内,若事件再次被触发,则重新计时,直到倒计时顺利结束,才执行事件回调
函数节流的原理是:触发事件后立即执行一次回调,但在n秒内对于再次触发的事件不予回应

实现代码如下:

/****1.防抖节流函数****/// 防抖:1s内再次触发事件则重新计时,直到倒计时结束才执行事件回调// 实现思路:在闭包中,内函数的定时器调用外函数的timer// 口诀:重复就清除,赋值不声明,延迟再执行functiondebounce(fn,delay){lettimer=null;returnfunction(...args){if(timer)clearTimeout(timer)timer=setTimeout(()=>{fn.apply(this,args)timer=null},delay)}}// 调用示例:document.getElementById("btn1").addEventListener("click",debounce(function(){console.log("点击防抖了...")},1000))// 节流:1s内只触发一次事件,期间再次触发不予回应// 实现思路:在闭包中,判断两次触发的时间是否大于1s(delay的值),是就执行// 口诀:新旧时间戳相减,间隔大于延迟就执行并更新functionthrottle(fn,delay){letlastTime=null;returnfunction(...args){constnowTime=Date.now()if(nowTime-lastTime>delay){fn.apply(this,args)lastTime=nowTime}}}//调用示例:document.getElementById("btn2").addEventListener("click",throttle(function(){console.log("点击节流了...")},1000))
2.对象深拷贝

思路是通过递归方法,对于对象属性仍为复杂类型时,递归调用当前函数,直到变为简单类型时返回

/****2.对象深拷贝****/// 实现思路:判断传参是否为简单类型,若是则直return,若否,声明一个变量(空对象或空数组),其类型取决于确定为复杂类型的传参的类型,遍历传参并判断当前属性是否是复杂类型,若是则递归调用functiondeepClone(obj){if(typeofobj!=='object'||obj===null)returnobjvarnewObj=Array.isArray(obj)?[]:{}for(letkeyinobj){if(obj.hasOwnProperty(key))newObj[key]=deepClone(obj[key])}returnnewObj}
3.数组去重
/*****3.数组去重*****/functionuniqueArr(arr){varnewArr=[]for(vari=0;i<arr.length;i++){if(newArr.indexOf(arr[i])==-1){//若是新数组中没有当前元素,则加入新数组中newArr.push(arr[i])}}returnnewArr}functionuniqueArr2(arr){returnArray.from(newSet(arr))}// 调用示例:console.log(uniqueArr([1,2,3,4,5,4,3,2,1]))
4.apply,call和bind方法
// 手写自定义的myCall// 1.绑定到Function的原型上,以便每个函数都能访问Function.prototype.MyCall=function(ctx,...args){//回顾:this指向call的第一个参数,而第二个和之后的参数用于传参// 2.如果ctx是null或undefined,则将ctx设置为全局对象ctx=ctx||window;// 3.利用Symbol的唯一性,创建一个独一无二的属性名,以防止覆盖原有属性constfnSymbol=Symbol();// 4.将当前函数this挂载到ctx上,作为其ctx对象的一个属性,以便在ctx上调用ctx[fnSymbol]=this;//call的第一个参数就是this指向的,也就是当前函数// 5.调用函数,并将剩余的参数传入constresult=ctx[fnSymbol](...args);//call的第二个参数以及以后的参数,都是传入的参数// 6.删除该属性deletectx[fnSymbol];// 7.返回结果returnresult;}//手写myApply方法,和myCall的唯一区别是第二个参数要写成数组形式// 手写自定义myApply,就是把...args换成数组ArrayargsFunction.prototype.MyApply=function(ctx,args){ctx=ctx||window;constfnSymbol=Symbol();ctx[fnSymbol]=this;constresult=ctx[fnSymbol](...args);deletectx[fnSymbol];returnresult;}//手写myBind方法,在闭包中调用myCall即可// 手写自定义的myBind,思路是返回一个函数,在该函数内部调用myCallFunction.prototype.MyBind=function(ctx,...args1){constthat=this;returnfunction(...args2){constargs=[...args1,...args2];returnthat.MyCall(ctx,...args)}}//测试用例:functiontest(a,b,c){console.log(this.name);console.log(a,b,c);}constobj={name:'obj'}constnewTest=test.MyBind(obj,1);newTest(2,3);//obj 1 2 3
5.new操作符

new一个对象时,发生了什么?

1.创建一个空对象,继承构造函数的原型2.执行构造函数:改变this指向3.判断对象类型,若是对象或函数,则直接返回;否则返回创建的空对象4.返回实例对象

实现代码:

functionmyNew(constructor,...args){// 1.创建一个空对象,继承构造函数的原型constobj=Object.create(constructor.prototype)// 2.执行构造函数:改变this指向constresult=constructor.apply(obj,args)// 3.判断对象类型,若是对象或函数,则直接返回;否则返回创建的空对象if(typeofresult==='object'&&result!==null||typeofresult==='function'){returnresult}// 4.返回实例对象returnobj;}//测试用例:functionPerson(name){this.name=name;}constp=myNew(Person,'test');console.log(p.name);// test
6.instanceof()方法

原生instanceof的作用和语法是:判断A是否是B的实例--instanceof(A,B)
判断条件:A的原型链上是否有B的prototype

functionMyInstanceof(A,B){// 1.若A是null或undefined直接返回falseif(A===null||typeofA!=='object')returnfalse;// 2.获取A的原型constproto=A.__proto__;// 3.遍历原型,直到找到B.prototype或nullwhile(true){if(proto===null)returnfalseif(proto===B.prototype)returntrueproto=proto.__proto__}}
http://www.jsqmd.com/news/670344/

相关文章:

  • Dubbo 超时机制与集群容错机制详解:防止雪崩的利器
  • 2026年降AI收藏指南:高效解决毕业论文AI率太高问题 - 降AI实验室
  • Qwen-Image-2512在Web开发中的应用:动态图像生成
  • 终极指南:如何用NHSE轻松打造你的完美动森岛屿
  • 那些年我们踩过的坑:CTF中栅栏密码、Base64与图片隐写的组合拳破解实录
  • 魔兽争霸III现代优化指南:WarcraftHelper让你的经典游戏焕发新生
  • 想装KBK柔性起重机,大型仓库适用的KBK轨道费用多少钱 - mypinpai
  • 解构 OPC:带你了解其背后的技术真实与商业幻觉
  • C++高性能计算项目集成:Phi-4-mini-reasoning辅助算法选择与内存优化
  • 终极Windows驱动清理指南:简单三步释放20GB磁盘空间
  • SolonCode vs OpenCode 内存实测,差距高达 8 倍!(此战能封神吗?)
  • 开源光学材料数据库:突破传统限制的3000+材料折射率解决方案
  • 2026年好用的凸轮分割器资深厂商推荐,价格多少钱 - 工业设备
  • 第31篇:从API到应用——调用OpenAI等接口,开发你的AI小工具(操作教程)
  • 5步指南:OBS多平台直播插件轻松实现一键多平台同时推流
  • 有实力的新西兰移民中介分析,移民之路不再迷茫 - 工业推荐榜
  • 2.5D转真人引擎行业标准构建:Anything to RealCharacters效果评估指标体系
  • StructBERT语义分析平台:快速搭建中文复述识别系统
  • 2026年3款降AI工具处理博士论文效果对比:10万字全文稳定性测评
  • 如何快速掌握SMUDebugTool:Ryzen处理器调试实用指南
  • BabelDOC:打破PDF翻译格式壁垒的智能文档处理引擎
  • 2026年3月数据机房消音器供货商口碑推荐,满足机房需求,提供可靠消音方案 - 品牌推荐师
  • 2026年靠谱的新西兰移民中介推荐,信誉良好机构选择指南 - myqiye
  • 春联生成模型-中文-base技术解析:如何保障对仗、平仄与文化适配性
  • Mysql自带三个核心数据库+SQL注入
  • 千问3.5-2B操作系统概念辅导:进程、线程与死锁问题排查
  • Blender + AI 如何结合使用?
  • zmq源码分析之mailbox_t
  • 深聊推荐天然气检测机构,费用和服务质量如何权衡 - 工业品牌热点
  • G-Helper:轻量级华硕笔记本性能管理解决方案