js原生api之String的slice方法

倚夢為碼發表於2018-11-27

  我們在工作中可能會很少進行這樣的思考,對於一些常用的原生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(`倚夢為碼!`);
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) //執行結果為 "夢為碼"
 
總結:在用js進行實現slice方法時尤其要注意臨界值的判斷條件,不能少判斷也不能做多餘的判斷防止演算法出現與原生slice方法有結果不一致的情況,而且在進行迴圈條件時應儘量做到不對全域性變數的屬性查詢之類的操作,因為這種操作的時間複雜度為 O(n) 。

我們可以在第一次對全域性變數進行屬性訪問時將其地址存到一個區域性變數中,這樣的話只會在第一次進行操作時會對全域性變數做屬性搜素,往後只需對區域性變數進行訪問,這時演算法複雜度只有 O(1),正所謂的即用即取。有興趣的小夥伴可以自己做做類似的練習。本文為作者  倚夢為碼  原創,歡迎大家觀看和轉載,若有其他用途請註明出處!謝謝合作!

 

相關文章