前端攻城獅學習筆記八:自己實現string的substring方法,人民幣小寫轉大寫,數字反轉,正則優化


  這是最近碰到的幾個題目,簡單地寫一下我自己的方案,在此分享給大家,也希望能看到大家的方案。

  水平有限,不保證我的方案絕對正確,如有錯誤歡迎指出。

一、自己實現string的substring方法

方法一:用charAt取出截取部分

String.prototype.mysubstring=function(beginIndex,endIndex){
    var str=this,
        newArr=[];
    if(!endIndex){
        endIndex=str.length;
    }
    for(var i=beginIndex;i<endIndex;i++){
        newArr.push(str.charAt(i));
    }
    return newArr.join("");
}

//test
"Hello world!".mysubstring(3);//"lo world!"
"Hello world!".mysubstring(3,7);//"lo w"

方法二:把字符串轉換成數組然后取出需要部分

String.prototype.mysubstring=function(beginIndex,endIndex){
    var str=this,
        strArr=str.split("");
    if(!endIndex){
        endIndex=str.length;
    }
    return strArr.slice(beginIndex,endIndex).join("");
}

//test
console.log("Hello world!".mysubstring(3));//"lo world!"
console.log("Hello world!".mysubstring(3,7));//"lo w"

方法三:取出頭尾部分,然后用replace去掉多余部分,適用於beginIndex較小,字符串長度-endIndex較小的情況

String.prototype.mysubstring=function(beginIndex,endIndex){
    var str=this,
        beginArr=[],
        endArr=[];
    if(!endIndex){
        endIndex=str.length;
    }
    for(var i=0;i<beginIndex;i++){
        beginArr.push(str.charAt(i));
    }
    for(var i=endIndex;i<str.length;i++){
        endArr.push(str.charAt(i));
    }
    return str.replace(beginArr.join(""),"").replace(endArr.join(""),"");
}

//test
console.log("Hello world!".mysubstring(3));//"lo world!"
console.log("Hello world!".mysubstring(3,7));//"lo w"

二、一萬億以內的人民幣小寫轉大寫,暫不考慮連續零的處理

方法一(七行代碼實現):

function moneyCaseConvert(num){
    var upperArr=["零","壹","貳","叄","肆","伍","陸","柒","捌","玖"],
        levelArr=["","拾","佰","仟","萬","拾","佰","仟","億","拾","佰","仟","萬"],
        numArr=num.toString().split("").reverse(),
        result=[];
    for(var i=numArr.length-1;i>=0;i--)
        result.push(upperArr[numArr[i]]+levelArr[i]);
    return result.join("");
}

//Test
console.log(CaseConversion(1234567891234));
//壹萬貳仟叄佰肆拾伍億陸仟柒佰捌拾玖萬壹仟貳佰叄拾肆

console.log(CaseConversion(987654321));
//玖億捌仟柒佰陸拾伍萬肆仟叄佰貳拾壹

console.log(CaseConversion(1234));
//壹仟貳佰叄拾肆

三、數字反轉,輸入123返回321

方法一:

function numReverse(num){
    return parseInt(num.toString().split("").reverse().join(""));
}

//Test
console.log(numReverse(123456));
//654321

方法二:

function numReverse(num){
    var numArr=num.toString().split(""),
        len=numArr.length,
        result=0;
    for(var i=len-1;i>=0;i--){
        result+=numArr[i]*Math.pow(10,i);
    }
    return result;
}

//Test
console.log(numReverse(123456));
//654321

四、JSONP原理,與Ajax的關系

  JSONP原理是利用了script標簽動態解析JS的特性,通過動態添加<script>標簽來調用服務器提供的js腳本,達到跨域調用的目地。關於JSONP更多信息可以參考這篇文章:http://kb.cnblogs.com/page/139725/

  JSONP與AJAX看起來有點像,目的也一樣,都是請求一個url,然后把服務器返回的數據進行處理,但JSONP與AJAX是兩個不同的東西,這兩者之間可以說沒什么關系。

五、正則表達式優化

  正則表達式的優化總的來說就是盡可能精確,減少回溯次數,具體來說主要是以下幾點:

  1. 如果你的正則工具支持,在不需要引用括號內文本的時候使用非捕獲型括號:(?:expression) 。
  2. 如果括號是非必須的,請不要加括號。
  3. 不要濫用字符數組,比如[.],請直接用\. 。
  4. 使用錨點^ $ ,這會加速定位。
  5. 從兩次中提取必須元素,如:x+寫成xx*,a{2,4}寫成aa{0,2}。
  6. 提取多選結構開頭的相同字符,如the|this 改成th(?:e|is)。(如果你的正則引擎不支持這么使用就改成th(e|is));尤其是錨點,一定要獨立出來,這樣很多正則編譯器會根據錨點進行特別的優化: ^123|^abc 改成^(?:123|abc)。同樣的$也盡量獨立出來。
  7. 多選結構后邊的一個表達式放入多選結構內,這樣能夠在匹配任何一個多選結構的時候在不退出多選結構的狀態下查看后一匹配,匹配失敗的更快。這種優化需要謹慎使用。
  8. 忽略優先匹配和優先匹配需要你視情況而定。如果你不確定,請使用匹配優先,它的速度是比忽略優先快的。
  9. 拆分較大正則表達式成一個個小的正則表達式,這是非常有利於提高效率的。
  10. 模擬錨點,使用合適的環視結構來預測合適的開始匹配位置,如匹配十二個月份,可以先預查首字符是否匹配:(?=JFMASOND)(?:Jan|Feb|…|Dec)。這種優化請根據實際情況使用,有時候環視結構開銷可能更大。

  注:以上幾點節選自http://blog.pureisle.net/archives/1447.html,非常好的一篇正則表達式優化文章,推薦有興趣的朋友看原文。

六、visibility:hidden與 display:none 的區別

  區別主要有三點:

  1、空間占據:元素設置為visibility:hidden后仍然占據物理空間,而元素設置為display:none后是不占據空間的。

  2、性能:visibility:hidden因為仍然占據物理空間,所以不會引起頁面的回流和重繪,所以性能更好,反之display:none會引起頁面回流和重繪。

  3、繼承性:當父元素設置為display:none后所有子元素均會被引藏,不改變父元素可見性的情況下子元素沒有辦法顯示出來,如果父元素設置為visibility:hidden,所有子元素也會不可見,但如果給子元素設置為visibility:visible的話,子元素就可以重見天日了。

七、篇歷DOM樹

方法一:用nextSibling和childNodes

function traversalByNextSibling(obj){
    var ch=obj.firstChild,
        result=[];
    do{
        result.push(ch.nodeName);
        if(ch.childNodes.length){
            result.push.apply(result,traversalByNextSibling(ch));
        }
    }while(ch=ch.nextSibling);
    return result;
}

方法二:用childNodes

function traversalByChildNodes(obj){
    var ch=obj.childNodes,
        result=[];
    for(var i=0,j=ch.length;i<j;i++){
        result.push(ch[i].nodeName);
        if(ch[i].childNodes.length){
            [].push.apply(result,traversalByChildNodes(ch[i]));
        }
    }
    return result;
}

測試:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Demo</title>
    <style type="text/css">
    
    </style>
</head>
<body>
    <div id="test">Test</div>
    <div>Hello World</div>
    <p>PTest</p>
    <script>
        console.log(traversalByNextSibling(document));
        //IE6-8: #comment,HTML,HEAD,TITLE,META,STYLE,BODY,DIV,#text,DIV,#text,P,#text,SCRIPT 
        //other:["html", "HTML", "HEAD", "#text", "META", "#text", "TITLE", "#text", "#text", "STYLE", "#text", "#text", "#text", "BODY", "#text", "DIV", "#text", "#text", "DIV", "#text", "#text", "P", "#text", "#text", "SCRIPT", "#text"]

        console.log(traversalByChildNodes(document));
        //IE6-8: #comment,HTML,HEAD,TITLE,META,STYLE,BODY,DIV,#text,DIV,#text,P,#text,SCRIPT 
        //otehr:["html", "HTML", "HEAD", "#text", "META", "#text", "TITLE", "#text", "#text", "STYLE", "#text", "#text", "#text", "BODY", "#text", "DIV", "#text", "#text", "DIV", "#text", "#text", "P", "#text", "#text", "SCRIPT", "#text"]
    </script>
</body>
</html>

  在IE6-8中把換行去掉了,在其他瀏覽器中把換行作為一個文本節點,所以會有很多#text,但IE6-8中出現了#comment我現在也沒明白為什么。

八、整數轉為千分位記數法

  方法一(解析字符串):

function numFormat(val){
    var numStr = val.toString(),
        length = numStr.length,
        extra = length % 3,
        count = (length - extra)/3,
        result = numStr.substr(0,extra);
    for(var i = 0; i < count; i++){
        result += "," + numStr.substr(extra+i * 3,3); 
    }
    return result.replace(/^,/,"");
}

//Test
console.log(numFormat(12));//12
console.log(numFormat(123));//123
console.log(numFormat(1234));//1,234
console.log(numFormat(123456789));//123,456,789

  方案二(正則):

function numberFormat(val){
    var numArr=String(val).split(".");
    numArr[0] = numArr[0].replace(new RegExp("(\\d)(?=(\\d{3})+$)","ig"),"$1,");
    return numArr.join(".");
}
//Test
console.log(numberFormat(123456));//123,456
console.log(numberFormat(12345678));//12,345,678

九、模擬一個HashTable類

  模擬一個HashTable類,有add、remove、containes、length方法

var HashTable =function(){
    this.container={
        length:0
    };
}

HashTable.prototype={
    add:function(key,value){
        if(key in this.container){
            return false;
        } else {
            this.container[key] = value;
            this.container.length++;
            return true;
        }
    },
    remove:function(key){
        if(key in this.container){
            delete this.container[key];
            this.container.length--;
            return true;
        }
    },
    containes:function(key){
        return (key in this.container);
    },
    length:function(){
        return this.container.length;
    }
}

var test = new HashTable();
test.add(1,123);
test.add(1,123);
test.add(2,123);
test.add(3,123);
test.add(4,123);
test.add(5,123);
console.log(test.containes(3));//true
console.log(test.length());//5
test.remove(3);
console.log(test.containes(3));//false
console.log(test.length());//4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM