知识点
padStart
,padEnd
及其polyfill- 字符串处理
题目
完成函数centerPad
可以让一个字符串被包裹在指定的可重复的字符串中间,例如:
centerPad('Hello', 13, 'abc') // => 'abcaHelloabca'
centerPad('Gook Luck!', 30, '*~') // => '*~*~*~*~*~Gook Luck!*~*~*~*~*~'
第一个参数为被包裹的字符串,第二个参数为最终的字符串长度,第三个参数为用来填充的字符。
如果字符串无法完全居中,那么让字符串偏左,例如:
centerPad('Hello', 10, 'abc') // => 'abHelloabc'
如果第二个参数传入的字符串长度比原来长度要短,直接返回原有字符串即可,例如:
centerPad('Hello', 1, 'abc') // => 'Hello'
实现
题目中有一个提示,可以充分利用ES6中新增的扩展方法。
可以利用的是ES7的padStart
,padEnd
方法,这两个方法用来将字符串在开头或者结尾填充字符串,直至指定的长度。接受两个参数,第一个参数是指定字符串的最终长度,第二个参数是当前用来填充的字符串。
如果当前字符串长度小于最小长度参数,会返回原字符串。
所以我们这里就可以使用这两个方法,先使用padEnd
填充字符串的右边,长度通过计算得来,然后使用padStart
填充左边
const centerPad = (str, len, pad) => {
if (str.length >= len) {
return str
}
const restTotal = len - str.length;
const restRight = Math.ceil(restTotal / 2) + str.length;
return str.padEnd(restRight, pad).padStart(len, pad)
};
polyfill
如果浏览器不支持的话怎么办呢?
我使用了Array.from
方法,来逐个填充字符串:
String.prototype.padStart2 = String.prototype.padStart2 || function (targetLength, padStrin
padString = String((typeof padString !== 'undefined' ? padString : ' '));
if (this.length > targetLength) {
return String(this)
} else {
targetLength = targetLength - this.length;
const padArray = Array.from(new Array(targetLength), (v, index) => {
let strIndex = index >= padString.length ? index % padString.length : index;
return padString[strIndex]
});
return padArray.join('') + String(this)
}
};
而MDN上给出的方法更巧妙,直接通过repeat
方法按照targetLength/padString.length
来填充,repeat
接受的参数会直接转换为整数(parseInt
,再通过累加一个padString
确保填充的长度大于实际需要的长度(实际上就是重复了Math.ceil(targetLength/padString.length)
遍)
然后在将截取(0, targetLength)
这个范围的结果就可以了。
还是更巧妙一些。
if (!String.prototype.padStart) {
String.prototype.padStart = function padStart(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 padString.slice(0, targetLength) + String(this);
}
};
}
使用我的方法,不利用padStart
也能实现:
const centerPad = (str, len, pad) => {
if (str.length >= len) {
return str
}
const restTotal = len - str.length;
const restRight = Array.from(new Array(Math.ceil(restTotal / 2)), (v, index) => {
let strIndex = index >= pad.length ? index % pad.length : index;
return pad[strIndex]
});
const restLeft = Array.from(new Array(Math.floor(restTotal / 2)), (v, index) => {
let strIndex = index >= pad.length ? index % pad.length : index;
return pad[strIndex]
});
return [...restLeft, str, ...restRight].join('')
};