我们在工作中可能会很少进行这样的思考,对于一些常用的原生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),正所谓的即用即取。有兴趣的小伙伴可以自己做做类似的练习。本文为作者  倚梦为码  原创,欢迎大家观看和转载,若有其他用途请注明出处!谢谢合作!

11-28 11:39