持续更新常见JavaScript算法
# 12300transform12,300functionthousandSeparator(number){letresult=[];letrest=String(Math.abs(number));while(rest.length){result.push(rest.slice(-3));rest=rest.slice(0,-3);}constr=result.reverse().join(",");returnnumber<0 ? "-"+r : r}console.log(666,thousandSeparator(12300))Array.prototype.myReduce=function(callback,initialValue){letarr=this;letpre=initialValue ? initialValue : arr[0];leti=initialValue ? 0 : 1;for(i;i<arr.length;i++){pre=callback(pre,arr[i]);}returnpre;}constres=[1,2,3,4].myReduce((pre,cur)=>{returnpre+cur;},1);console.log('myReduce',res);varPerson=function(name,age){this.name=name;this.age=age;}Person.prototype.test="this is a test";Person.prototype.testFunc=function(){console.log('this is a testFunc');}// 子类varStudent=function(name,age,gender,score){Person.apply(this,[name,age]);// 盗用构造函数this.gender=gender;this.score=score;}// 1. 改变 Student 构造函数的原型对象// Student.prototype = new Person(); // 2.圣杯模式Student.prototype=Object.create(Person.prototype);Student.prototype.constructor=Student;Student.prototype.testStuFunc=function(){console.log('this is a testStuFunc');}// 测试varzhangsan=newStudent("张三",18,"男",100);console.log(zhangsan.name);// 张三console.log(zhangsan.age);// 18console.log(zhangsan.gender);// 男console.log(zhangsan.score);// 100console.log(zhangsan.test);// this is a testzhangsan.testFunc();// this is a testFunczhangsan.testStuFunc();// this is a testStuFuncconsole.log(Student.prototype)functionP(age,country){console.log(`Hello, my name is ${this.name} and I am ${age}, I am from ${country}`);}/*1. call 函数允许你在特定上下文中调用函数function.call(context, arg1, arg2, ...)2. apply 函数与 call 函数类似,也允许你在特定上下文中调用函数。不同之处在于 apply 函数需要以数组形式传递参数function.apply(context, [argsArray])1. bind 函数与 call 和 apply 函数不同。它不会立即调用函数。而是返回一个将绑定到指定上下文的新函数,当调用该函数时,它将以指定的上下文运行。function.bind(thisArg, arg1, arg2, ...)*/P.call({name: 'mary'},'12','USA')P.apply({name: 'lilei'},['13','France'])P.bind({name: 'tom'},'11','China')// 5. 自定义call、apply、bind// 实现call方法Function.prototype.myCall=function(context, ...args){// 如果context参数为空,则默认为window对象context=context||window;// 使用Symbol函数创建唯一标识符constfnSymbol=Symbol();// 将原始函数存储为context对象的属性context[fnSymbol]=this;// 调用函数并将结果存储在 result 变量中constresult=context[fnSymbol](...args);// 删除 context 对象的属性deletecontext[fnSymbol];// 返回函数的结果returnresult;};// 实现 apply 方法Function.prototype.myApply=function(context,args){// 如果 context 参数为空,则默认为 window 对象context=context||window;// 使用 Symbol 函数创建唯一标识符constfnSymbol=Symbol();// 将原始函数存储为 context 对象的属性context[fnSymbol]=this;// 调用函数并将结果存储在 result 变量中constresult=context[fnSymbol](...args);// 删除 context 对象的属性deletecontext[fnSymbol];// 返回函数的结果returnresult;};// 实现 bind 方法Function.prototype.myBind=function(context, ...args){// 将 this 绑定到 fn 变量中constfn=this;// 返回一个新函数,该函数将传递的参数与新函数的参数合并,并在新上下文中使用 apply 调用原始函数returnfunction(...newArgs){returnfn.apply(context,[...args, ...newArgs]);};};P.myCall({name: 'mary'},'12','USA')P.myApply({name: 'lilei'},['13','France'])P.myBind({name: 'tom'},'11','China')constcheckIfInstanceOf=(obj,classFunction)=>{if(classFunction===null)returnfalse;while(obj!==null){if(obj.__proto__===classFunction.prototype){returntrue};obj=obj.__proto__;}returnfalse;}classAnimal{};classDogextendsAnimal{};console.log('checkIfInstanceOf',checkIfInstanceOf(newDate(),Date))// trueconsole.log('checkIfInstanceOf',checkIfInstanceOf(newDog(),Animal))// trueconsole.log('checkIfInstanceOf',checkIfInstanceOf(Date,Date))// falseconsole.log('checkIfInstanceOf',checkIfInstanceOf(5,Number))// trueconsole.log('checkIfInstanceOf',checkIfInstanceOf([],Array))// trueArray.prototype.last=function(){constlen=this.lengthreturnlen ? this[len-1] : -1}console.log([1,2,3].last());// 3console.log([].last());// -1/** * @param {number} n * @return {Function} counter */varcreateCounter=function(n){returnfunction(){returnn++};};constcounter=createCounter(10)counter()// 10counter()// 11counter()// 12/** * @param {number} millis * @return {Promise} */asyncfunctionsleep(millis){returnnewPromise((resolve,reject)=>{setTimeout(resolve,millis)})}lett=Date.now()sleep(100).then(()=>console.log(Date.now()-t))// 100/** * @param {Array} arr * @param {number} depth * @return {Array} */Array.prototype.myFlat=function(deep){letarr=this;letresult=[];if(deep===0){returnarr;}for(leti=0;i<arr.length;i++){if(Array.isArray(arr[i])){result.push(...arr[i].myFlat(deep-1));}else{result.push(arr[i]);}}returnresult;}console.log('myFlat',[1,2,3,[4,5,6],[7,8,[9,10,11],12],[13,14,15]].myFlat(2))Number.prototype.add=function(n){returnthis+n}Number.prototype.sub=function(n){returnthis-n}console.log('(5).add(3).sub(2)',(5).add(3).sub(2))// 6constmyAdd=(min,max)=>{letsum=0for(leti=min;i<=max;i++){sum=sum+i}returnsum}console.log('myAdd',myAdd(1,100))// 在西雅图的公司远程工作,因为月中算法考核,半月的绩效奖金没了。。。constintersect=function(nums1,nums2){letresult=[]letlongArr=nums1.length>nums2.length ? nums1 : nums2;letshortArr=nums1.length>nums2.length ? nums2 : nums1;for(leti=0;i<shortArr.length;i++){letlongIndex=longArr.indexOf(shortArr[i])if(longIndex!=-1){result.push(longArr.splice(longIndex,1)[0])}}returnresult};intersect([1,2,1,2],[2,2,2])// [2, 2, 2]intersect([4,9,5],[9,4,9,8,4])// [4, 9]intersect([3,1,2],[2,2])// [2]/** * @param {number[]} nums * @return {number[]} */constsortArray=function(nums){const{ length }=nums;for(leti=0;i<length;i++){for(letj=0;j<length-1-i;j++){if(nums[j]>nums[j+1]){[nums[j],nums[j+1]]=[nums[j+1],nums[j]];}}}returnnums;};sortArray([1,3,9,5,2,4,6])/* 在这种情况下,curry 函数接受一个函数 fn 作为参数,并返回一个经过 currying 的新函数。在调用 curryed 函数时,它会检查传入的参数数量是否大于或等于原函数 fn 的参数数量(arity)。如果是,则直接调用原函数;否则,它会返回一个接受剩余参数(rest)的新函数,并将之前传入的参数(args)与剩余参数合并,然后再调用 curryed 函数。这样就实现了函数 currying。*/constcurry=(fn)=>{constarity=fn.length;returnfunctioncurried(...args){if(args.length>=arity){returnfn.apply(this,args);}else{returnfunction(...rest){returncurried.apply(this,args.concat(rest));};}};}constgetURL=(protocol,domain,path)=>{returnprotocol+"://"+domain+"/"+path;}constmyurl=getURL('http','mysite','home.html');constmyurl2=getURL('http','mysite','about.html');console.log('myurl',myurl);console.log('myurl2',myurl2);constcurry=(fn)=>{constarity=fn.length;returnfunctioncurried(...args){if(args.length>=arity){returnfn.apply(this,args);}else{returnfunction(...rest){returncurried.apply(this,args.concat(rest));};}};}constgetURL=(protocol,domain,path)=>{returnprotocol+"://"+domain+"/"+path;}constmyurl=getURL('http','mysite','home.html');constmyurl2=getURL('http','mysite','about.html');console.log('myurl',myurl);console.log('myurl2',myurl2);// 减少重复传递不变的参数constsuperGetURL=curry(getURL)('https','mysite');constmyurl3=superGetURL('detail.html')console.log('myurl3',myurl3);varPerson=function(name,age){this.name=name;this.age=age;}Person.prototype.test="this is a test";Person.prototype.testFunc=function(){console.log('this is a testFunc');}varStudent=function(name,age,gender,score){Person.apply(this,[name,age]);// Stealing the constructorthis.gender=gender;this.score=score;}Student.prototype=newPerson();// Change the prototype object of the Student constructorStudent.prototype.testStuFunc=function(){console.log('this is a testStuFunc');}// 测试varzhangsan=newStudent("张三",18,"男",100);console.log(zhangsan.name);// 张三console.log(zhangsan.age);// 18console.log(zhangsan.gender);// 男console.log(zhangsan.score);// 100console.log(zhangsan.test);// this is a testzhangsan.testFunc();// this is a testFunczhangsan.testStuFunc();// this is a testStuFunc