本文转载至张鑫旭的博文 from www.zhangxinxu.com/wordpress/?…
在JS中,字符串补全是经常使用操做,用的比较多的就是时间或者日期前面的补0
。
javascript
例如,日期,咱们多采用4-2-2的表示形式,例如:php
2018-07-23复制代码
当咱们使用时间戳进行月份获取的时候,是没有前面的0
的,例如:前端
var month = new Date().getMonth() + 1; // 结果是7复制代码
此时,就须要进行补全,一般作法是这样:java
if (month < 10) {
month = '0' + month;
}复制代码
甚至会专门定义一个补'0'
方法,例如此日期转时间戳微码中的自定义的zero
方法。git
然而,随着JS字符串补全方法padStart()
和padEnd()
的出现,相似场景使用就简单多了!github
padStart
能够在字符串的开头进行字符补全。windows
语法以下:后端
str.padStart(targetLength [, padString])复制代码
其中:浏览器
targetLength
指目标字符串长度。
而后,根据个人测试,targetLength
参数缺省也不会报错,本来的字符串原封不动返回,不过代码没有任何意义,所以,基本上没有使用的理由。less
还有,targetLength
参数的类型能够是数值类型或者弱数值类型。在JavaScript中,1 == '1'
,1
是数值,'1'
虽然本质上是字符串,但也能够当作是弱数值。在padStart()
方法中,数值类型或者弱数值类型都是能够。例如:
'zhangxinxu'.padStart('5');复制代码
所以,咱们实际使用的时候,不必对targetLength
参数进行强制的类型转换。
最后,若是targetLength
设置的长度比字符串自己还要小,则本来的字符串原封不动返回,例如:
'zhangxinxu'.padStart(5);
// 结果仍是'zhangxinxu'复制代码
padString
表示用来补全长度的字符串。然而,虽然语义上是字符串,可是根据个人测试,任意类型的值都是能够的。不管是Chrome浏览器仍是Firefox浏览器,都会尝试将这个参数转换成字符串进行补全。例以下面几个例子:
'zhangxinxu'.padStart(15, false);
// 结果是'falsezhangxinxu'复制代码
'zhangxinxu'.padStart(15, null);
// 结果是'nullnzhangxinxu'复制代码
'zhangxinxu'.padStart(15, []);
// 结果是'zhangxinxu',由于[]转换成字符串是空字符串复制代码
'zhangxinxu'.padStart(15, {});
// 结果是'[objezhangxinxu',只显示了'[object Object]'前5个字符复制代码
padString
参数默认值是普通空格' '
(U+0020),也就是敲Space空格键出现的空格。
从上面几个案例能够看出,若是补全字符串长度不足,则不断循环补全;若是长度超出,则从左侧开始依次补全,没有补到的字符串直接就忽略。
此方法返回值是补全后的字符串。
回到一开始的日期补'0'
功能,有了padStart()
方法,咱们代码能够简化成下面这一行:
var month = String(new Date().getMonth() + 1).padStart(2, '0'); // 结果是'07'复制代码
兼容性
IE14以其已下浏览器都不支持,考虑到如今仍是windows 7天下,PC端对外项目还不能直接用;移动端,UC浏览器,QQ浏览器也不支持。可是,也不是不能使用,加一个Polyfill就行了,这个后面会展现。
padEnd
能够在字符串的后面进行字符补全,语法参数等都和padStart
相似。
语法:
str.padEnd(targetLength [, padString])复制代码
其中:
targetLength
指补全后字符串的长度。
而后,根据个人测试,targetLength
参数若是不设置,不会报错,直接返回原始字符串,不过这样代码就没有任何意义,所以,实际开发,此参数确定是须要设置的。
一样的,targetLength
参数的类型能够是数值类型或者弱数值类型。例以下面2个用法都是能够的:
'zhangxinxu'.padEnd('15');
'zhangxinxu'.padEnd(15);复制代码
所以,咱们实际写代码的时候,不必强制targetLength
参数为数值。
最后,若是targetLength
设置的长度比字符串自己还要小,则原字符串原封不动返回,例如:
'zhangxinxu'.padEnd(5);
// 结果仍是'zhangxinxu'复制代码
若是targetLength
是一些乱七八糟的数值类型,也是返回原始字符串。例如:
'zhangxinxu'.padEnd(false);
// 结果仍是'zhangxinxu'复制代码
可是有意义吗?没意义,因此不要这么用。
padString
表示用来补全长度的字符串。虽然语义上是字符串,实际上这个参数能够是各类类型。例以下面几个例子:
'zhangxinxu'.padEnd(15, false);
// 结果是'zhangxinxufalse'复制代码
'zhangxinxu'.padEnd(15, null);
// 结果是'zhangxinxunulln'复制代码
'zhangxinxu'.padEnd(15, []);
// 结果是'zhangxinxu',由于[]转换成字符串是空字符串复制代码
'zhangxinxu'.padEnd(15, {});
// 结果是'zhangxinxu[obje',只显示了'[object Object]'前5个字符复制代码
从上面几个案例能够看出,若是补全字符串长度不足,则从左往右不断循环补全;若是长度超出能够补全的字符长度,则从左侧尽量补全,补不到的没办法,只能忽略,例如'zhangxinxu'.padEnd(15, {})
等同于执行'zhangxinxu'.padEnd(15, '[object Object]')
,最多只能补5个字符,所以,只能补'[object Object]'
前5个字符,因而最后结果是:'zhangxinxu[obje'
。
padString
参数若是不设置,则会使用普通空格' '
(U+0020)代替,也就是Space空格键敲出来的那个空格。
举一个在后面补全字符串案例
在JS前端咱们处理时间戳的时候单位都是ms
毫秒,可是,后端同窗返回的时间戳则不同是毫秒,可能只有10位,以s
秒为单位。因此,咱们在前端处理这个时间戳的时候,保险起见,要先作一个13位的补全,保证单位是毫秒。使用示意:
timestamp = +String(timestamp).padEnd(13, '0');复制代码
兼容性
本字符串API属于ES6新增方法,IE14以其已下浏览器都不支持,部分国产移动端浏览器也不支持。目前对外项目使用还须要附上Polyfill代码。
如下Polyfill代码取自polyfill项目中的string.polyfill.js,其中使用依赖的repeat()
也是ES6新增方法,所以,完成Polyfill代码以下,注释部分我作了简单的翻译,代码部分简化了些许逻辑,同时,修复了一个bug,下面代码红色高亮部分就是修复内容:
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// repeat()方法的polyfill
if (!String.prototype.repeat) {
String.prototype.repeat = function (count) {
'use strict';
if (this == null) {
throw new TypeError('can\'t convert ' + this + ' to object');
}
var str = '' + this;
count = +count;
if (count != count) {
count = 0;
}
if (count < 0) {
throw new RangeError('repeat count must be non-negative');
}
if (count == Infinity) {
throw new RangeError('repeat count must be less than infinity');
}
count = Math.floor(count);
if (str.length == 0 || count == 0) {
return '';
}
if (str.length * count >= 1 << 28) {
throw new RangeError('repeat count must not overflow maximum string size');
}
var rpt = '';
for (; ;) {
if ((count & 1) == 1) {
rpt += str;
}
count >>>= 1;
if (count == 0) {
break;
}
str += str;
}
return rpt;
}
}
// padStart()方法的polyfill
if (!String.prototype.padStart) {
String.prototype.padStart = function (targetLength, padString) {
// 截断数字或将非数字转换为0
targetLength = targetLength>>0;
padString = String((typeof padString !== 'undefined' ? padString : ' '));
if (this.length > targetLength || padString === '') {
return String(this);
}
targetLength = targetLength-this.length;
if (targetLength > padString.length) {
// 添加到初始值以确保长度足够
padString += padString.repeat(targetLength / padString.length);
}
return padString.slice(0, targetLength) + String(this);
};
}
// padEnd()方法的polyfill
if (!String.prototype.padEnd) {
String.prototype.padEnd = function (targetLength, padString) {
// 转数值或者非数值转换成0
targetLength = targetLength >> 0;
padString = String((typeof padString !== 'undefined' ? padString : ' '));
if (this.length > targetLength || padString === '') {
return String(this);
}
targetLength = targetLength - this.length;
if (targetLength > padString.length) {
// 添加到初始值以确保长度足够
padString += padString.repeat(targetLength / padString.length);
}
return String(this) + padString.slice(0, targetLength);
};
}复制代码
以上polyfill代码须要放在调用padStart()
/padEnd()
方法的代码的前面,只要在合适的位置就这么一粘贴,而后,不管什么版本浏览器浏览器,哪怕IE6,IE8,咱们也能够放心使用padStart()
或者padEnd()
方法了。
polyfill代码下的demo案例
您能够狠狠地点击这里:padStart和padEnd方法polyfill测试demo
原polyfill方法的一个bug就是经过这个测试demo测出来的,下面是修正后的polyfill代码在IE9浏览器的测试结果截图:
标题虽然是简介,可是本文内容实际上已经很是深刻细节了。padStart()
和padEnd()
两个方法参数容错性很是强,很是有JS的特点,我很喜欢。可是,也带来另外的问题,就是,若是咱们的参数值由于各类缘由,最后并非咱们指望的参数值,则极可能会产生很是隐蔽的bug,由于不会报错啊,运行仍是正常的。因此,容错性强,也算是有利有弊。