当前位置: 首页 > Web前端 > vue.js

js进阶手写常用功能

时间:2023-03-31 22:59:38 vue.js

进阶JavaScript的必要性无论是学习react还是vue,都是js应用框架。剥开它们的壳看到的永远是js,所以作为前端大厨,必须掌握好js的大勺子,才能做出一桌好菜。无论是自我提升还是面试,以下手写函数是每个前端程序员必须掌握的1.手写apply、call、bind每个Function对象都有apply()、call()、bind()方法,其function是在特定范围内调用函数,相当于在函数体中设置this对象的值,扩大函数运行的范围。apply、call、bind的异同1.三个都可以改变this的方向,第一个参数是this,如果指向的是null或者undefined,则指向window2.apply的参数是一个数组,call是一个列表,bind可以多次传入3.apply和call是改变this的方向后直接运行函数,而bind是绑定后返回函数apply的引用代码/***手写apply*/window.name='gy'//全局变量letobj={name:'ckx'}varfunc=function(b,c){console.log(`this=`,this)console.log(this.name,b,c)return1}func('24','hz')//gy24hzfunc.apply(obj,['24','hz'])//ckx24hzletnewObj={name:'xmx',age:24}Function.prototype.myApply=function(base,args){//1.如果指针为空或未定义,则指向窗口base=base||window//2.根据谁调用this就指向谁this是谁的原则,给this指向的函数赋值给base对象一个属性base.fn=this//3.执行函数,当base.fn被调用,fn中的函数指向base对象letresult=base.fn(...args)//4.删除basefn属性deletebase.fn//5.returnresultresultreturnresult}func.myApply(newObj,['55','yw'])//xmx55ywapply代码执行效果相关js视频讲解:进入学习调用实现参考代码/***手写调用*/window.name='gy'//全局变量letobj={name:'ckx'}varfunc=function(b,c){console.log(`this=`,this)控制台。日志(这。name,b,c)return1}func('24','hz')//gy24hzfunc.call(obj,'24','hz')//ckx24hzletnewObj={name:'xmx',age:24}//call和apply需要注意参数的格式Function.prototype.myCall=function(base,...args){//1.如果指针为null或undefined,则指向到窗口base=base||window//2.根据谁调用this指向谁的原则,将this指向的函数赋值给base对象的一个??属性base.fn=this//3.执行函数,当调用base.fn时,fn中的函数函数指向base对象letresult=base.fn(...args)//4.删除base的fn属性deletebase.fn//5.返回结果returnresult}func.myCall(newObj,'55','yw')//xmx55ywcall代码执行效果bind实现参考代码/***手写bind*/window.name="gy";//全局变量letobj={name:"ckx",};varfunc=function(b,c,d){console.log(`this=`,this);console.log(this.name,b,c,d);返回1;};func("24","hz",26);//gy24hz26letfuncRes=func.bind(obj,"24","hz");funcRes(24);//ckx24hz24letnewObj={name:"xmx",age:24,};//注意bind返回的绑定函数和可以多次传递的参数Function.prototype.myBind=function(base,...args1){return(...args2)=>{//1.如果指针为空或未定义,则指向窗口base=base||窗户;//2.根据this是谁指向谁调用的原则,将this指向的函数赋值给基对象的一个??属性base.fn=this;//3.执行函数,调用base.fn时,fn中的函数指向base对象letresult=base.fn(...args1,...args2);//4.删除base的fn属性deletebase.fn;//5.返回结果返回结果;};};letmyfuncRes=func.myBind(newObj,"55","yw")myfuncRes(24)//xmx55yw24bind代码执行效果2.手写newnew关键字执行时做了什么1.创建一个new对象2.使用这个新对象的原型和构造函数链接链3.将构造函数的this指向新对象,执行构造函数的代码赋值4.如果构造函数没有返回对象,返回新建对象否则返回构造函数返回的对象手写new参考代码/****手写new关键字执行*/functionPerson(name,age){this.name=name;}Person.prototype.getName=function(){returnthis.name;};leta=newPerson('gy');console.log(a);console.log(a.getName());constmyNew=(Func,...args)=>{让newObj={};newObj.__proto__=Func.prototypeletresult=Func.apply(newObj,args)returntypeofresult==Object?result:newObj};letb=myNew(Person,'gy1')console.log(b);console.log(b.getName());代码执行结果参考图原型链图3.手写instanceoftypeof可以判断basic数据类型为null,但返回的对象也无法识别引用数据类型instanceof可以准确判断引用数据类型但无法判断基本数据类型instanceof用于检测构造函数的原型是否有原型链实例对象引用代码/***手写instanceof*/letobj={label:'gy'}letarr=['hello']letresult=objinstanceofObjectletresult1=arrinstanceofArrayletresult2=arrinstanceofObjectletresult3=objinstanceofArrayconsole.log('result=',result)console.log('result1=',result1)console.log('result2=',result2)console.log('result3=',result3)constmyInstanceof=(left,right)=>{if(typeofleft!='object'||left==null)returnfalseletproto=Object.getPrototypeOf(left)while(true){if(proto==null)返回falseif(proto==right.prototype)返回trueproto=Object.getPrototypeOf(proto)}}constmyResult=myInstanceof(obj,Object)constmyResult1=myInstanceof(arr,Array)constmyResult2=myInstanceof(arr,Object)constmyResult3=myInstanceof(obj,Array)console.log('myRsult=',myResult)console.log('myResult1=',myResult1)console.log('myResult2=',myResult2)console.log('myResult3=',myResult3)代码执行结果截图根据上面的代码打印结果,需要注意的是一切都是对象,包括数组。如果有一个变量(arrOrObj),它可能是一个数组或一个对象。如果用instanceof判断,首先要判断是不是数组,否则arrOrObjinstanceofObject一定为true,无法区分数组和对象。触发,从新开始倒计时一定时间后会继续触发,延迟n秒后执行回调,未到n秒时重新开始,不会重新计时的使用场景二。防抖可能用于不可预知的用户主动行为,比如用户打字的速度是不可预知的、无规律的。Throttling可能用于一些非用户主动行为或可预测的用户主动行为,比如用户滑动产品窗口时发送埋点请求,滑动固定高度是已知逻辑,具有规律性。节流防抖也是关闭应用手写防抖代码参考/****手写防抖*/constdebounce=(func,delay)=>{lettimer=null;返回函数(...args){如果(计时器){clearTimeout(计时器);定时器=空;}timer=setTimeout(()=>{func(args);},delay);};};constgetfn=(data)=>{console.log(data);};debounce(getfn,2000)("gy");手写防抖代码执行结果Handwrittenthrottling/****Handwrittenthrottling*这里只需要注意和防抖不同时不会清零的时序*/constthrottle=(func,delay)=>{让标志=假;returnfunction(...args){if(flag)returnflag=truesetTimeout(()=>{func(args);flag=false},delay);};};constgetfn=(data)=>{console.log(data);};throttle(getfn,2000)("gy");5.AjaxAJAX全称AsynchronousJavaScript+XML,最重要的是XHR(XMLHttpRequest)XMLHttpRequest请求特定的URL而不刷新页面获取数据。实现要求XMLHttpRequest()是一个构造函数XMLHttpRequest.onreadystatechange状态码改变时触发事件(所有浏览器都支持)XMLHttpRequest.readyState请求状态码XMLHttpRequest.status响应状态码返回标准的HTTP状态码其他请求响应这是整个响应实体XMLHttpRequest.responseTextreturns`DOMString`XMLHttpRequest.timeouttimeoutXMLHttpRequest.upload上传进度检查常用方法open()//method/url是必须的xhr.open(method,url,async,user,password);send()//bodyoptionaldefaultisnull//canbeBlob,BufferSource(en-US),FormData,//URLSearchParams,orUSVStringobject.XMLHttpRequest.send(body);setRequestHeader()XMLHttpRequest.setRequestHeader(header,value);//例如,XMLHttpRequest.setRequestHeader("content-type","application/x-www-form-urlencoded");基于以上API实现ajax1.构造一个请求XMLHttpRequest2.初始化一个请求打开3.监听请求onreadystatechange4.发送请求send/***手写ajax*/constmyAjax=(url,methods,header,success,error)=>{//创建请求letrequest=newXMLHttpRequest()//Setrequestheaderfor(constkeyinheader){request.setRequestHeader(key,header[key])}//初始化请求request.open(methods,url)//发送请求request.send()//监听请求onreadystatechangerequest.onreadystatechange=function(){if(request.readyState==4){if(request.status==200){success(request.response)}else{error()}}}}