自己实现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更多信息可以参考这篇文章:https://www.jb51.net/article/31167.htm。
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)。这种优化请根据实际情况使用,有时候环视结构开销可能更大。
注:以上几点节选自https://www.jb51.net/article/31168.htm,非常好的一篇正则表达式优化文章,推荐有兴趣的朋友看原文。
六、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){
result.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我现在也没明白为什么。
一、自己实现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更多信息可以参考这篇文章:https://www.jb51.net/article/31167.htm。
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)。这种优化请根据实际情况使用,有时候环视结构开销可能更大。
注:以上几点节选自https://www.jb51.net/article/31168.htm,非常好的一篇正则表达式优化文章,推荐有兴趣的朋友看原文。
六、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){
result.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我现在也没明白为什么。