当前位置: 首页 > Web前端 > JavaScript

我手写的一些js系列

时间:2023-03-27 13:41:17 JavaScript

alert输出的是字符串1,手写的call&bind~functionanonymous(proto){functionbind(context=window,...args){return(...amArgs)=>{this.apply(context,args.conact(amArgs));}}函数调用(context,...args){context===null?上下文=窗口:空;让type=typeof上下文;if(type!=='object'&&type!=='function'&&type!=='symbol'){switch(type){case"number":context=newNumber(context);}休息;case'string':context=newString(context);休息;case'boolean':context=newBoolean(context);休息;}}context.$fn=this;让result=context.$fn(...args)删除context.$fn;返回结果;}proto.call=callproto.bind=bind}(Function.prototype)二、节流与防抖节流:执行多少秒,如果在执行时间前继续点击,重新计算执行时间application:inputoutputfunctiondebounce(fn,delay){lettimer=null;返回函数(){如果(计时器){clearTimeout(timer)}timer=setTimeout(()=>{fn.call(this,...arguments)timer=null;},delay)}}//示例:handleChange=(e)=>{this.value=e.target.value;}Input.onChange=debounce(handleChange,500);Input.onChange=function(){if(timer){clearTimeout(timer);}timer=setTimeout(()=>{handleChange.call(this,...arguments)},500)}防抖:设置两秒间隔点击一次,无论点击多少次,应用将在两秒后执行:resize,scroll1,timestampfunctionthrottle(fn,interval){//立即执行letlast=newDate().getTime();returnfunction(){letnow=newDate().getTime();如果(现在-最后>间隔){最后=现在;fn.apply(this,[...arguments])}}}2.定时器函数throttle(fn,interval){lettimer=nullreturnfunction(){if(!timer){timer=setTimeout(()=>{fn.apply(this,[arguments])clearTimeout(timer)},interval)}}}3.时间戳和定时器功能throttle的结合le(fn,delay){//节流10lettimer=null;让startTime=newDate().getTime();30返回函数(){letcurTime=newDate().getTime();让remaining=delay-(curTime-startTime);让上下文=这个;让args=参数;清除超时(计时器);如果(剩余<=0){fn.apply(上下文,参数);开始时间=当前时间;}else{timer=setTimeout(fn,剩余);}}}三、实现一个新函数self_new(Func,...args){//默认创建一个实例对象(并且是当前类的实例)letobj={};对象。__proto__==Func.prototype;//大多数IE浏览器不允许我们直接操作__proto__;//让obj=Object.create(Dog.prototype);等价于上面两行letresult=Func.call(obj,...args);if((typeofresult==='object'&&result!==null)||(typeofresult==='function')){returnresult}returnobj;//也把类作为普通函数执行//执行时,保证this指向创建的实例}4.继承的四种方式1.原型继承函数A(){this.x=100;}A.prototype.getX=functiongetX(){console.log(this.x)}functionB(){this.y=200;}//原型继承B.prototype=newA()B.prototype.getY=functiongetY(){console.log(this.y);}让b=新B;//特点:不是将父类的方法克隆到子类,而是在子类和父类之间建立原型链搜索机制//子类原型重定向后,默认会丢失原有的构造函数属性,//任何子类都可以修改父类上的属性方法,//父类的私有属性方法成为子类的公共属性2,调用继承函数A(){this.x=100;}A.prototype.getX=functiongetX(){console.log(this.x)}//将父类作为普通函数执行,执行时方法中的this成为子类函数B的一个实例(){A.调用(B);这个.y=200;}B.prototype.getY=functiongetY(){console.log(this.y)}letb=newB;//只能继承父类的私有属性,继承的私有属性赋值给子类实例的私有属性//不能继承父类的原型方法3.寄生组合继承(完美)//调用继承实现私有属性继承//原型继承实现公有属性继承函数A(){this.x=100;}A.prototype.getX=functiongetX(){console.log(this.x)}//将父类作为普通函数执行,让其执行时,方法中的this成为子类函数的实例B(){A.调用(B);这个.y=200;}//Object.create:创建一个空对象,让它的__proto__指向A.prototypeB.prototype=Object.create(A.prototype);B.prototype.constructor=B.prototype.getY=functiongetY(){console.log(this.y)}letb=newB;4.class继承classA{constructor(){this.x=100;}//在A.prototype上设置方法num=1000;//设置A的属性和方法为普通对象staticn=2000;staticgetH(){console.log('123123')}getX(){console.log(this.x)}}classBextendsA{constructor(){super();这个.y=300;}getY(){console.log(this.y);}}5。深拷贝JSON。parse(JSON.stringify(obj))缺陷:转义后正则=>{}function=>nullfunctiondeepClone(obj){if(obj===null)returnnull;//如果是基本数据值或函数,也可以直接返回(函数不需要克隆)if(typeofobj!=='object')returnobj;//如果是正则if(Object.toString.call(obj)==='[ObjectRegExp]')returnnewRegExp(obj);//如果是日期格式if(Object.toString.call(obj)==='[ObjectDate]')returnnewDate(obj);//obj.constructor:找到它所属的类原型上的构造函数,原型上的构造函数指向当前类本身==>保证传入的是什么类型的值,而我们最后得到的newObjcreated也是对应的类型letnewObj=newobj.constructor;for(letkeyinobj){if(!obj.hasOwnProperty(key))中断;newObj[key]=deepClone(obj[key])}returnnewObj;}6.实现promiseclassMyPromise{constructor(executor){//每个promise实例都有一个状态和结果属性this.PromiseStatus='pending';this.PromiseValue=undefined;this.reveveFnArr=[];this.rejectFnArr=[]//定义resolve/reject方法,用于改变promise实例的状态和结果letchange=(status,value)=>{if(this.PromiseStatus!=='pending')return;this.PromiseValue=值;this.PromiseStatus=status;letfnArr=status==='已解决'?this.reveveFnArr:this.rejectFnArr;fnArr.forEach(item=>{if(typeofitem!=='function'){return}item(this.PromiseValue);})}letresolve=result=>{if(this.reveveFnArr.length){change('已解决',结果)返回}让delayTimer=setTimeout(()=>{更改('已解决',结果)clearTimeout(delayTimer)},0)}letreject=resason=>{if(this.reveveFnArr.length){change('rejected',resason)return}letdelayTimer=setTimeout(()=>{change('resolved',result)clearTimeout(delayTimer)},0)}//每个新的Promise都会执行执行函数try{executor(resolve,reject);}catch(err){拒绝(err);}}then(resolveFn,rejectFn){//每次执行then都会返回一个新的promise实例//this.reveveFnArr.push(resolveFn);//this.rejectFnArr.push(rejectFn);//如果传递的参数不是函数(null/或未传递),我们让传递成功或失败if(typeofresolveFn!=='function'){resolveFn=(result)=>{returnresult;}}if(typeofrejectFn!=='function'){rejectFn=(reason)=>{returnMyPromise.reject(reason);}}returnnewMyPromise((resolve,reject)=>{//执行resolve/reject判断新实例成功还是失败//executor函数中只执行新实例resolve/reject将知道新实例是成功还是失败。this.reveveFnArr.push((result)=>{try{//如果没有报错,则接受该方法的返回结果,根据结果判断成功或失败letx=resolveFn(result);console.log('设置then执行的数据',x,xinstanceofMyPromise)if(xinstanceofMyPromise){x.then(resolve,reject);return}resolve(x);}catch(err){//执行出错表示新实例失败reject(err)}});this.rejectFnArr.push((reason)=>{try{//如果没有报错,则接受该方法的返回结果,根据结果判断成功或失败letx=rejectFn(reason);if(xinstanceofMyPromise){x.then(resolve,reject);return}resolve(x);}catch(err){//执行错误表示新实例失败reject(err)}});})}//MyPromise.prototype.catch(fn)===MyPromise.prototye.then(null,fn)catch(rejectFn){returnthis.then(null,rejectFn);}//静态方法staticresolve(result){returnnewMyPromise((resolve,re项目)=>{解决(结果);})}staticreject(reason){returnnewMyPromise((resolve,reject)=>{reject(reason);})}staticall(arr){returnnewMyPromise((resolve,reject)=>{letindex=0;letresults=[];for(leti=0;i{index++;results[i]=result;if(index===arr.length){resolve(results);}}).catch(reason=>{reject(reason)})}})}}七、大数相加functionadd(str1,str2){letnum1=str1.split('').reverse();让num2=str2.split('').reverse();console.log(num1,num2)让nextNum=0;让总计=[];for(leti=0;i=10){nextNum=String(curNum)[0];total.push(字符串(curNum)[1]);}else{nextNum=0;total.push(curNum)}}else{curNum=Number(num2[i])+nextNum;如果(curNum>=10){nextNum=String(curNum)[0];total.push(字符串(curNum)[1]);}else{nextNum=0total.push(curNum)}}}returntotal.reverse().join('');}letd=add("123456789123456789123456789123456789123456789123456734","1241519123456789123456789123456789123456789123456789123451234567891")