merge/Aop切面编程/千分符/urlparams/日期格式化

267 阅读2分钟

merge

merge方法就是把两个对象合并,如果是B向A合并,就要以B为主 合并规则: A没有的B有的把b的加到a里,A,B都有的(除了A是引用数据类型,B是基本数据类型)B修改A,如果A,B都是普通对象,那么A,B也要合并,合并后的结果给A对应的属性

代码

这种合并就是发生在普通对象上,要保证传入的两个实参是普通对象,使用Object.prototype.toString.call(item)是否为"[object Object]"来确定了

	function isObj(obj){
    	return Object.prototype.toString.call(obj)==="[object Object]"
    }
	function merge(pre,cur){
    
    	if(!isObj(pre)||!isObj(cur)){
        	throw new Error("传入的参数不正确")
        }
        for(let k in cur){
        	let preVal=pre[key]
            let curVal=cur[key]
            if(/^(object|fucntion)$/.test(preVal)&&!								  (/^(object|fucntion)$/.test(curVal))){
            	throw new Error("数据结构冲突")
            }
            if(isObj(preVal)&&isObj(curVal)){
            	pre[key]=merge(pre[key],cur[key])
            }else{
            	pre[key]=cur[key]
            }
        }
        return pre
    }

Aop切面编程

通常情况下我问设置一个方法,在这个方法执行前和执行后也要有一些操作Function.prototype上可以设置before和after方法,方法实例调用before/after的方法传入要执行的函数,返回的方法执行就先执行了before传入的方法,之后执行调用它的方法本身

Function.prototype.before=function(callback){
	if(typeof callback!=="function"){
    	throw new Error("您传入的不是函数")
    }
    let _this=this
	return fucntion(...args){
    	callback.call(this,...args)
        _this.call(this,...args)
    }
}
Function.prototype.after=function(callback){
	if(typeof callback!=="function"){
    	throw new Error("您传入的不是函数")
    }
    let _this=this
	return fucntion(...args){
        _this.call(this,...args)
        callback.call(this,...args)
    }
}

使用

	function fn(){
    	console.log(1)
    }
    fn.before(()=>console.log(0)).after(()=>console.log(2))

千分符

对钱数实现,的分割,从后数每三个一个, 把顺序倒过来,每三个一循环加,来实现

	function formatMoney(money){
    	//把传进来的无论是数字还是字符串转成字符串
    	money=""+money
        //转成数组并倒过来
        money=money.split("").reverse()
        for(var i=2;i<money.length-1;i+=3){
        	money.splice(i+1,0,",")
            i++
        }
    	money=return money.reverse().join("")
        return money
    }

利用正则来实现: 前面一定有数字1~3个,后面一定是三的倍数个数字,要替换的是前面的数字,所以后面的数字不能捕获,用到正向预查只匹配不补获,捕获的地方要被替换,后面加一个","

	function formatMoney(money){
    	money=""+money
        retrun money.replace(/\d{1,3}(?=(\d{3})+$)/g,_=>{
        	return _+","
        })
    }
function getQuery(url){
    const reg=/([^?#=&]+)=([^?#=&]+)/g
    const hash=/#([^?=&#])/g
    const obj={}
    url.replace(reg,(...[,$1,$2])=>{
            obj[$1]=$2
    })
    url.replace(hash,(...[,$1])=>{
            obj.hash=$1
    })
    return obj
}

题目

编写queryURLParams方法实现如下效果 let url="www.zhufengpeixun.cn/?lx=1&from=…" console.log(url.queryURLParams("from")) //=>"wx" console.log(url.queryURLParams("-HASH")) //=>"video"

方法一

正则方法

String.prototype.queryURLParams=function(strKey){
    const regQuery=/([^?=#&]+)=([^?=#&]+)/g    
    //提取query的正则只要=两边的的值
    const regHash=/#([^?&=#]+)/g
    //提取hash的正则,要#之后的内容
    const obj={}
    this.replace(regQuery,(_,$1,$2)=>{
        $1?obj[$1]=$2:null
    })
    this.replace(regHash,(_,$1)=>{
        obj["_HASH"]=$1
    })
    return obj[strKey]
}

方法二

传统方法:切割

String.prototype.queryURLParams=function(strName){
        let quIndex=this.indexof("?"),      //得到?的索引值
            hashIndex=this.indexof("#"),       //得到#的索引值
            quStr="",                       //存储hash值
            hashStr="",                     //存储query的值
            obj={}                          //存储最后的结果
        if(hashIndex>-1){               //判断是否存在hash
           hashStr= this.substring(hashIndex+1)             
           //拿到字符串中#后面的所有字符串
        }
        hashIndex=hashIndex>-1?hashIndex:this.length
        //获取query截取的末尾值有hash就是#的索引值否则就是到头
        if(quIndex>-1){         //判断是否存在query
            quStr=this.substring(quIndex+1,hashIndex)
        }
        hashStr?obj["_HASH"]=hashStr:null
        if(quStr){      //存在query
            const array=quStr.split("&")
            array.forEach(item=>{
           if( item.indexof("=")===-1) return
               let newarr= item.split("=")      //是否存在key
             obj[newarr[0]]=newarr[1]:null
            })
        }
        return strName?obj[strName]:obj
        
        
    }
    

总结

首先indexof得到?和#的index,根据两个index得到?之后#之前的query和#之后的hash 有可能没有?或#

方法三

利用a标签的search和hash和正则

String.prototype.queryURLParams=function(strName){
    const link=document.createElement("a")
    link.href=this
    let query=link.search?link.search.substring(1):""
    let hash=link.hash?link.hash.substring(1):""
    const obj={}
    obj["_HASH"]=hash
    const newarr=query.split(/(?:=|&)/g)
    for(var i=0;i<newarr.length;i+=2){
          let key=newarr[i]
          let value=newarr[i+1]
          obj[key]=value
    })
    return strName?obj[strName]:obj
}

大致思路

对给出的日期字符串("1999-03-10 12:00:12")转化成1999年03月10日 12时00分12秒 为字符串的原型对象中添加方法,方法传入模板字符串 首先要将原始的时间字符串通过通过正则和match方法得到所有匹配值组成的数组 这个数组的索引与模板的{}中的数字对应

代码

    /**
        formatDate格式化时间字符串,得到想要的格式
          @params: 
                template:时间的模板  例如:{0}年{1}月{2}日 {3}时{4}分{5}秒
    */
    function formatDate(template="{0}年{1}月{2}日 {3}时{4}分{5}秒"){ 
        let dateArr=this.match(/\d+/g)  //得到待格式化的字符串中数字
        template.replace(/\{(\d+)\}/g,(...arg)=>{   //每当正则匹配上一次就调用一次
            const [,$1]=arg
            let time=dataArr[$1] || "00"        //如果数组中没有这个值就返回"00"
            return count.length<2?"0"+time:time //长度小于2补零,返回的值会替换匹配上的部分
        })
    }
    String.prototype.formatDate=formatDate