本文轉載至張鑫旭的博文 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,由於不會報錯啊,運行仍是正常的。因此,容錯性強,也算是有利有弊。