这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战。
前言
ECMAScript 6.0 简称ES6 , 是 JavaScript 语言的新一代的标准,于在 2015 年 6 月发布,正式名称就是《ECMAScript 2015 标准》。一般情况,泛指, 5.1版以后的标准,涵盖了 ES2015、ES2016、ES2017、ES2018、ES2019、ES2020、ES2021 等等
我们一起来学习和自己实现:
- String.prototype.padStart
- String.prototype.padEnd
这两个都是字符串补全的方法,一个前面补全,一个后面补全。
String.prototype.padStart
使用一个字符串填充当前字符串,以便产生的字符串达到给定的长度。
语法
str.padStart(targetLength [, padString])
- targetLength 需要保持的长度
- padString
填充的字符串, 默认值为
" "
一起来看看经典应用:
日期填充
把日期转为 "yyyy-mm-dd"格式, 因为月和日可能小于10, 不足两位,之前主要是通过判断数字是都大于10来做填充,现在可就简单多了。
const date = new Date(2020,1,1);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const ddate = date.getDate();
const dateStr = year + "-" +
(month + "").padStart(2, "0") + "-"
+ (ddate + "").padStart(2, "0")
// 2020-02-01
编码填充
我们把码点转为 二进制或者16进制等等, 因为我们一般是8个比特位一组。
低于0xFFFF码点的字符转为\uxxxx格式, 转为二进制也是类得的。
"\\u" + "a".codePointAt(0).toString(16).padStart(4, "0") // '\u0061'
特殊情况
长度值小于0
第一个参数长度都还好理解,毕竟嘛,如果小于0,负数,就以字符串的自身长度为准。
"a".padStart(0, "0") // 'a'
"a".padStart(-10, "0") // 'a'
长度参数不是数字
如果第一个参数,不是数字呢? 可以猜想到,依旧是自身的长度为准。
"a".padStart(NaN, "0") // 'a'
"a".padStart({}, "0") // 'a'
填充字符
第二参数如果是undefined或者null
"a".padStart(5, undefined) // ' a'
"a".padStart(5, null) // 'nulla'
到这里,基本可以理解了,如果是undefined,就采用默认值 " ",不然就把其值转为字符串。
"a".padStart(5, {}) // '[obja' 这里还可以看出会截断
"a".padStart(5, 10.2) // '10.2a'
这里,你可能还想想到 Symbol呢?
"a".padStart(5, Symbol.for("a"))
也许到这里,你觉得你懂了,我们再换一个
"a".padStart(5, []) // 'a'
哈哈,是不是有一点小惊喜。 这里因为 []转为字符串后是 ""字符串,如果填充字符是空字符串,是不会进行填充的。
基于ES5 Polyfill
思路当然是检查长度,如果不够,逐个添加。
当然更多的实现细节得参考 ES实现标准 StringPad
如下是MDN的实现:
if (!String.prototype.padStart) {
String.prototype.padStart = function padStart(targetLength,padString) {
targetLength = targetLength >> 0;
padString = typeof padString !== 'undefined' ? padString + '' : ' ');
if (this.length > targetLength) {
return String(this);
}
else {
targetLength = targetLength - this.length;
if (targetLength > padString.length) {
padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed
}
return padString.slice(0,targetLength) + String(this);
}
};
}
这里有两个细节:
- targetLength >> 0
通过位移获得数字,我们单独讲解。 - padString.repeat
repeat也是ES6出现的,需要自己额外实现。
不借助repeat我们怎么实现呢? for循环,当然。
String.prototype.padEnd
与padStart非常类似,不做过多介绍。
"a".padEnd(4, "0") // 'a000'
MDN的Polyfill, 思路也非常的类似。
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
if (!String.prototype.padEnd) {
String.prototype.padEnd = function padEnd(targetLength,padString) {
targetLength = targetLength>>0; //floor if number or convert non-number to 0;
padString = String((typeof padString !== 'undefined' ? padString: ''));
if (this.length > targetLength) {
return String(this);
}
else {
targetLength = targetLength-this.length;
if (targetLength > padString.length) {
padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed
}
return String(this) + padString.slice(0,targetLength);
}
};
}
小结
今天你收获了吗?