参考答案:
实现的方法有很多,以下介绍几种。
空数组 join
1function repeat(target, n) { 2 return (new Array(n + 1)).join(target); 3}
改良方法1,省去创建数组这一步,提高性能。之所以创建一个带 length 属性的对象,是因为要调用数组的原型方法,需要指定 call 第一个参数为类数组对象。
1function repeat(target, n) { 2 return Array.prototype.join.call({ 3 length: n + 1 4 }, target); 5}
改良方法 2,利用闭包缓存 join,避免重复创建对象、寻找方法。
1var repeat = (function () { 2 var join = Array.prototype.join, obj = {}; 3 return function(target, n) { 4 obj.length = n + 1; 5 return join.call(obj, target); 6 }; 7})();
使用二分法,减少操作次数
1function repeat(target, n) { 2 var s = target, total = []; 3 while (n > 0) { 4 if (n % 2 === 1) { 5 total[total.length] = s; 6 } 7 if (n === 1) { 8 break; 9 } 10 11 s += s; 12 n = n >> 1; // Math.floor(n / 2); 13 } 14 return total.join(''); 15}
方法 4 的变种,免去创建数组与使用 join。缺点是循环中创建的字符串比要求的长。
1function repeat(target, n) { 2 var s = target, c = s.length * n; 3 do { 4 s += s; 5 } while (n = n >> 1) 6 s = s.substring(0, c); 7 return s; 8}
方法 4 的改良。
1function repeat(target, n) { 2 var s = target, total = ""; 3 while (n > 0) { 4 if (n % 2 === 1) { 5 total += s; 6 } 7 if (n === 1) { 8 break; 9 } 10 s += s; 11 n = n >> 1; 12 } 13 return total; 14}
与 6 相近,不过递归在浏览器中有优化。
1function repeat(target, n) { 2 if (n === 1) { 3 return target; 4 } 5 var s = repeat(target, Math.floor(n / 2)); 6 s += s; 7 if (n % 2) { 8 s += target; 9 } 10 return s; 11}
一则反例,很慢,但是可行。
1function repeat(target, n) { 2 return (n <= 0) ? "" : target.concat(repeat(target, --n)); 3}
最后给出 MDN 中的String.prototype.repeat
的 polyfill 方法,大家也可以进行参考:
1if (!String.prototype.repeat) { 2 String.prototype.repeat = function(count) { 3 'use strict'; 4 if (this == null) 5 throw new TypeError('can\'t convert ' + this + ' to object'); 6 7 var str = '' + this; 8 // To convert string to integer. 9 count = +count; 10 // Check NaN 11 if (count != count) 12 count = 0; 13 14 if (count < 0) 15 throw new RangeError('repeat count must be non-negative'); 16 17 if (count == Infinity) 18 throw new RangeError('repeat count must be less than infinity'); 19 20 count = Math.floor(count); 21 if (str.length == 0 || count == 0) 22 return ''; 23 24 // Ensuring count is a 31-bit integer allows us to heavily optimize the 25 // main part. But anyway, most current (August 2014) browsers can't handle 26 // strings 1 << 28 chars or longer, so: 27 if (str.length * count >= 1 << 28) 28 throw new RangeError('repeat count must not overflow maximum string size'); 29 30 var maxCount = str.length * count; 31 count = Math.floor(Math.log(count) / Math.log(2)); 32 while (count) { 33 str += str; 34 count--; 35 } 36 str += str.substring(0, maxCount - str.length); 37 return str; 38 } 39}
最近更新时间:2024-07-20