我們在工作中可能會很少進行這樣的思考,對於一些常用的原生api它是如何實現的呢,如果讓我們去用js實現一個與原生api功能相同的函數我們該如何設計演算法去實現呢? 為了鞏固自己的編程技術和提高自己的編程技巧,也為了讓自己對js這門語言有更深刻的理解,我將會把平時開發常用到的各種原生api用自己的方式去 ...
我們在工作中可能會很少進行這樣的思考,對於一些常用的原生api它是如何實現的呢,如果讓我們去用js實現一個與原生api功能相同的函數我們該如何設計演算法去實現呢?
為了鞏固自己的編程技術和提高自己的編程技巧,也為了讓自己對js這門語言有更深刻的理解,我將會把平時開發常用到的各種原生api用自己的方式去實現,如果有錯誤的地方或者代碼運行效率有更好的實現方案歡迎大神指正和批評
本次將要實現的第一個方法是Javascript的String基本類型和String對象的常用方法 slice
slice的定義和用法 (紅色文字部分摘自菜鳥教程,slice方法)
slice(start, end) 方法可提取字元串的某個部分,並以新的字元串返回被提取的部分。使用 start(包含) 和 end(不包含) 參數來指定字元串提取的部分。
字元串中第一個字元位置為 0, 第二個字元位置為 1, 以此類推。
提示: 如果是負數,則該參數規定的是從字元串的尾部開始算起的位置。也就是說,-1 指字元串的最後一個字元,-2 指倒數第二個字元,以此類推。
start:必須. 要抽取的片斷的起始下標。第一個字元位置為 0
end:可選。 緊接著要截取的片段結尾的下標。若未指定此參數,則要提取的子串包括 start 到原字元串結尾的字元串。
如果該參數是負數,那麼它規定的是從字元串的尾部開始算起的位置。
slice()方法在第一個參數為負數時不管第二個參數為正數還是負數都會返回"";第二個參數為負數時會將負的參數加上字元串的長度。
1 var sliceYMWM=function(s,start,end){ 2 // 首先我們的方法得滿足大前提,s必須為String類型或者是String對象的實例 3 if(typeof(s) == 'string' || s instanceof String){ 4 var slen=s.length; 5 var aglen=arguments.length; 6 var res=""; 7 // 我們先處理只用兩個參數 s 和 start 的情況 8 if(aglen==2){ 9 if(start>slen){ //此時起始索引大於串長返回空串 10 return res; 11 }else if(start>0&&start<slen){ 12 for(let i = start; i<slen; i++){ 13 res+=s[i]; 14 } 15 return res; 16 }else{ 17 for(let q = slen+start; q<slen; q++){ 18 res+=s[q]; 19 } 20 return res; 21 } 22 }else if(aglen==3){//當三個參數都有的情況 23 if(start<0){//第一個參數 start 為負數時,都會返回 "" 24 return res; 25 }else{ 26 if(end<0){ //當第三個參數 end 為負數時,需要加串長轉換成正序的索引 27 if(start<end+slen){ 28 for(let j= start; j<end+slen;j++){ 29 res+=s[j]; 30 } 31 return res; 32 }else{ //此時起始索引大於等於結束索引返回空串 33 return res; 34 } 35 }else{ 36 if(start<end){ //當結束索引大於串長時,須改良迴圈結構的退出條件,否則當結束索引遠大於串長時會做無用的性能消耗 37 if(end<slen){ 38 for(let k=start; k<end;k++){ 39 res+=s[k]; 40 } 41 return res; 42 }else{ 43 for(let k=start; k<slen;k++){ 44 res+=s[k]; 45 } 46 return res; 47 } 48 }else{ //此時起始索引大於等於結束索引返回空串 49 return res; 50 } 51 } 52 } 53 }else{ 54 throw "參數個數不滿足要求!"; 55 } 56 }else{ 57 throw "傳入的s並非是字元串類型或者是字元串對象!"; 58 59 } 60 } 61 var s1=new String('倚夢為碼!');總結:在用js進行實現slice方法時尤其要註意臨界值的判斷條件,不能少判斷也不能做多餘的判斷防止演算法出現與原生slice方法有結果不一致的情況,而且在進行迴圈條件時應儘量做到不對全局變數的屬性查找之類的操作,因為這種操作的時間複雜度為 O(n) 。
62 var s1_=sliceYMWM(s1,0); //運行結果為 String {"倚夢為碼!"} 63 var s2='倚夢為碼!';
64 var s2_=sliceYMWM(s2,0); //運行結果為 "倚夢為碼!"
65 var s3_=sliceYMWM(s2,-2); // 運行結果為 "碼!"
66 var s4_=sliceYMWM(s2,1,-1) //運行結果為 "夢為碼"
我們可以在第一次對全局變數進行屬性訪問時將其地址存到一個局部變數中,這樣的話只會在第一次進行操作時會對全局變數做屬性搜素,往後只需對局部變數進行訪問,這時演算法複雜度只有 O(1),正所謂的即用即取。有興趣的小伙伴可以自己做做類似的練習。本文為作者 倚夢為碼 原創,歡迎大家觀看和轉載,若有其他用途請註明出處!謝謝合作!