js将字符串重复N次的repeat方法的8个版本

/*
*@desc: 将一个字符串重复自身N次
*/
//版本1:利用空数组的join方法
function repeat(target, n) {
return (new Array(n + 1)).join(target);
}
//版本2:之所以要创建一个带length属性的对象 是因为要调用数据的原型方法,需要指定call的第一个参数为类数组对象
//类数组对象的必要条件是其length属性的值为非负数
function repeat(target, n) {
return Array.prototype.join.call({
length: n + 1
}, target);
}
//版本3:利用闭包将类数组对象与数组原型的join方法缓存起来
var repeat = (function () {
var join = Array.prototype.join, obj = {};
return function (target, n) {
obj.length = n + 1;
return join.call(obj, target);
}
})(); //版本4:使用二分法
function repeat(target, n) {
var s = target, total = [];
while (n > 0) {
if (n % 2 == 1) {
total[total.length] = s;//如果是奇数
}
if (n == 1) {
break;
} s += s;
n = n >> 1;//相当于将n除以2取其商,或者说是开2次方
}
return total.join('');
}
//版本5:版本4的改良版本
function repeat(target, n) {
var s = target, total = "";
while (n > 0) {
if (n % 2 == 1) {
total += s;
}
if (n == 1) {
break;
} s += s;
n = n >> 1;//相当于将n除以2取其商,或者说是开2次方
}
return total;
}
//版本6:版本4的变样版本 免去创建数组与使用join方法 但在循环中创建字符串比要求的还长 所以...
function repeat(target, n) {
var s = target, c = s.length * n;
do {
s += s;
} while (n = n >> 1);
s = s.substring(0, c);
return s;
} //版本7:版本5的优化版本
function repeat(target, n) {
if (n == 1) {
return target;
}
var s = repeat(target, Math.floor(n / 2));
s += s;
if (n % 2) {
s += target;
}
return s;
}
//版本8:反例
function repeat(target, n) {
return (n <= 0) ? "" : target.concat(repeat(target, --n));
}

大家可以猜猜哪个运行速度最快。事实上应该是版本5.

事实上业余时间一直都在关注一些js性能方面的东西,跟.net一样,每种语言的代码都有些性能方面的小常识。

(有空可以看看  我总结的js方面你可能不是特别清楚的小知识   我总结的js性能优化的小知识     )

回到正题

下面来说说。。。

trim方法的各种不同版本(13种不同方法实现)

/*
*@desc:去掉首尾空格
*/
//版本1:
function trim(str) {
return str.replace(/^\s\s*/, '').replace('/\s\s*$/', '');
}
//版本2:比版本1稍微慢些
function trim(str) {
return str.replace(/^\s+/, '').replace('/\s+$/', '');//比版本1慢的原因在于它最先假设至少存在一个空白符
}
//版本3:运用等巧妙的
function trim(str) {
return str.substring(Math.max(str.search(/\S/), 0), str.search(/\S\s*$/) + 1);
}
//版本4:jQuery类库就是使用这种方法 但是它相对之前三个都要慢些
function trim(str) {
return str.replace(/^\s+|\s+$/g, '');
}
//版本5:
function trim(str) {
str = str.match(/\S+(?:\s+\S+)*/);//使用非捕获性分组(?:expr)
return str ? str[0] : '';
}
//版本6:效率挺差
function trim(str) {
return str.replace(/^\s*(\S*(\s+\S+)*)\s*$/, '$1');
}
//版本7:比版本6来说使用了非捕获性分组
function trim(str) {
return str.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, '$1');
}
//版本8:效果秒杀
function trim(str) {
return str.replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');
}
//版本9:使用懒惰匹配
function trim(str) {
return str.replace(/^\s*([\S\s]*?)\s*$/, '$1');
}
//版本10:速度最快
function trim(str) {
var whitespace = '\n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
for (var i = 0; i < str.length; i++) {
if (whitespace.indexOf(str.charCodeAt(i)) === -1) {
str = str.substring(i);
break;
}
}
for (i = str.length - 1; i >= 0; i--) {
if (whitespace.indexOf(str.charCodeAt(i)) === -1) {
str = str.substring(0, i + 1);
break;
}
}
return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}
//版本11:
function trim(str) {
str = str.replace('^\s+', '');
for (var i = str.length - 1 ; i >= 0; i--) {
if (/\S/.test(str.charAt(i))) {
str = str.substring(0, i + 1);
break;
}
}
return str;
}
//版本12:
function trim(str) {
var str = str.replace(/^\s\s*/, ''),
ws = /\s/,
i = str.length;
while (ws.test(str.charAt(--i))) {
return str.slice(0, i + 1);
} }
//版本13:仅次于版本10
function trim(str) {
var m = str.length;
for (var i = -1; str.charCodeAt(++i) <= 32;)
for (var j = 0; j > i && str.charCodeAt(j) <= 32; j--) {
return str.slice(i, j + 1);
}
}

与trim相反,下面说说为字符串的某一端填充字符串,其实最常见的场景就是日期中的月份前补零

pad:这字符串的某一端填充字符串

/*
*@desc:给字符串的某一端填充字符串
*/
//版本1:创建数组来放置填充物,然后再在右边起截取
function pad(target, n) {
var zero = new Array(n).join('0'),
str = zero + target,
result = str.substr(-n);
return result;
}
//版本2:
function pad(target, n) {
return Array((n + 1) - target.toString().split('').length).join('0') + target;
}
//版本3:二进制法
function pad(target, n) {
return (Math.pow(10, n) + "" + target).slice(-n);
}
//版本4:Math.pow
function pad(target, n) {
return ((1 << n).toString(2) + target).slice(-n);
}
//版本5:toFixed
function pad(target, n) {
return (0..toFixed(n) + target).slice(-n);
}
//版本6:创建一个超大数,在常规情况下截不完
function pad(target, n) {
return (1e20 + '' + target).slice(-n);
}
//版本7:质朴长存法
function pad(target, n) {
var len = target.toString().length;
while (len < n) {
target = '0' + target;
len++;
}
return target;
}
//版本8:支持更多参数
function pad(target, n, filling, right, radix) {
var num = target.toString(radix || 10);
filling = filling || '0';
while (num.length < n) {
if (!right) {
num = filling + num;
} else {
num += filling;
}
}
return num;
}

取得字符串所有字节的长度

大家都知道,一个中文字符占两个字节,而一个英文字符只占一个字符,所以在前端就会免不了做字符长度的校验。

/*
*@desc:取得字符串所有字节的长度
*/
//版本1:传统常规作法
function byteLen(target) {
var byteLength = target.length, i = 0;
for (; i< target.length; i++) {
if (target.charCodeAt(i)>255) {
byteLength++;
}
}
return byteLength;
}
//版本8:使用正则
//param:fix 默认为2 可传入转换长度
function byteLen(target,fix) {
fix = fix ? fix : 2;
var str = new Array(fix + 1).join('-');
return target.replace(/[^\x00-\xff]/g, str).length;
}

再来说说我们最常使用的js字符串方法吧

常用的js字符串方法

/*
*@desc: 判断一个字符串是否包含另一个字符串
*/
function contains(target, str, separator) {
return separator ?
(separator + target + separator).indexOf(separator + str + separator) > -1 :
target.indexOf(str) > -1;
}
/*
*@desc: 判断目标字符串是否位于原字符串的开始之处
*@param:ignorecase 是否忽略大小写
*/
function startsWith(target, str, ignorecase) {
var start_str = target.substr(0, str.length);
return ignorecase ?
start_str.toLowerCase() === str.toLowerCase() :
start_str === str;
}
/*
*@desc: 判断目标字符串是否位于原字符串的末尾之处
*/
function endsWith(target, str, ignorecase) {
var end_str = target.substr(0, str.length);
return ignorecase ?
end_str.toLowerCase() === str.toLowerCase() :
end_str === str;
} /*
*@desc: 对字符串进行截断处理,当超过限定长度,默认添加三个点号或者...
*/
function truncate(target, length, truncation) {
length = length || 30;
truncation = truncation === void (0) ? '...' : truncation;
return target.length > length ?
target.slice(0, length - truncation.length) + truncation : String(target);
}
/*
*@desc: 转换为下划线风格
*/
function underscored(target) {
return target.replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/\-/g, '_').toLowerCase();
}
/*
*@desc: 转换为连字符风格
*/
function dasherize(target) {
return underscored(target).replace(/_/g, '-');
}
/*
*@desc: 首字母大写
*/
function capitalize(target) {
return target.charAt(0).toUpperCase() + target.substring(1).toLowerCase();
}
/*
*@desc: 移除字符串中的html标签
*/
function stripTags(target) {
return String(target || '').replace(/<[^>]+>/g, '');
} /*
*@desc: 移除字符串中所有的script标签
*/
function stripScripts(target) {
return String(target || '').replace(/<script[^>]*>([\S\s]*?)<\/script>/img, '');
}
/*
*@desc: 将字符串经过html转义得到适合在页面上显示的内容
*/
function escapeHTML(target) {
return target.repeat(/&/g, '&amp;')
.repeat(/</g, '&lt;')
.repeat(/>/g, '&gt;')
.repeat(/"/g, '&quot;')
.repeat(/'/g, ''');
}
/*
*@desc: 将字符串中的html实体字符还原为对应字符
*/
function unescapeHTML(target) {//
return target.repeat(/&lt;/g, '<')
.repeat(/&gt;/g, '>')
.repeat(/&quot;/g, '"')
.repeat(/&amp;/g, '&')
.repeat(/&#([\d]+);/g, function ($0, $1) {
return String.fromCharCode(parseInt($1, 10));
});
}
/*
*@desc: 将字符串安全格式化为正则表达式的源码
*/
function escapeRegExp(target) {
return target.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
}
/*
*@desc: 为目标字符串添加软换行
*/
function wbr(target) {
return String(target).replace(/(?:<[^>]+>)|(?:&#?[0-9a-z]{2,6};)|(.{1})/gi, '$&<wbr>').replace('/><wbr>/g', '>');
}
/*
*@desc: 格式化
*/
function format(str, object) {
var array = Array.prototype.slice.call(arguments, 1);
return str.replace(/\\?\#{([^{}]+)\}/gm, function (match, name) {
if (match.charAt(0)=='\\') {
return match.slice(1);
}
var index = Number(name);
if (index>=0) {
return array[index];
}
if (object&&object[name]!=void 0) {
return object[name];
}
return '';
});
}

顺便说说上述format方法的使用吧

        var a = format('Result is #{0},#{1}', 22, 33);
console.log(a);
var b = format("#{name}is a #{sex}", {
name: "Jhon",
sex: 'man'
});
console.log(b);

运行结果如下图:

js数组方法的扩展

大家都知道js数组没有像字符串一样的indexOf、lastIndexOf等方法,那我们先来造造轮子吧。先来扩展一下吧!

/*
*@desc:定位操作,返回数组中第一个等于给定参数的元素的索引值
*/
Array.prototype.indexOf = function (item, index) {
var n = this.length, i = ~~index;
if (i < 0) {
i += n;
}
for (; i < n; i++) {
if (this[i] === item) {
return i;
}
}
return -1;
}
/*
*@desc:与lastIndex功能类似 不过是从后遍历
*/
Array.prototype.lastIndexOf = function (item,index) {
var n = this.length,
i = index == null ? n - 1 : index;
if (i<0) {
i = Math.max(0, n + i);
}
for (; i > length; i--) {
if (this[i]===item) {
return i;
}
}
return -1;
}
/*
*@desc:因为forEach、map、filter、some、every这几个方法结构相似 所以... 先造个轮子
*/
function iterator(vars,body,ret) {
var fun = 'for(var ' + vars + 'i=0,n=this.length;i<n;i++){' +
body.replace('_', '((i in this ) && fn.call(scope ,this[i],i,this))') + '}' + ret;;
return Function("fn,scope", fun);
}
/*
*@desc:将数组中的元素依次传入一个函数中运行
*/
Array.prototype.forEach = iterator('', '_', '');
/*
*@desc:将数组中的元素依次传入一个函数中运行 将返回值为ture的那个元素放入新数组中返回
*/
Array.prototype.filter = iterator('r=[],j=0,', 'if(_)r[j++]=this[i]', 'return r');
/*
*@desc:收集、将数组中的元素依次传入一个函数中运行 然后把它们的返回值组成一个新数组返回
*/
Array.prototype.map = iterator('r=[],', 'r[i]=_', 'return r');
/*
*@desc:只有数组中的元素有一个元素满足条件则返回true
*/
Array.prototype.some = iterator('', 'if(_) return true', 'return false');
/*
*@desc:只有数组中的元素都满足条件才返回true
*/
Array.prototype.every = iterator('', 'if(!_) return false', 'return true'); /*
*@desc:归化操作,将数组中的元素归化为一个简单的数值
*/
Array.prototype.reduce = function (fn,lastResult,scope) {
if (this.length == 0) {
return lastResult;
}
var i = lastResult != undefined ? 0 : 1;
var result = lastResult != undefined ? lastResult : this[0];
for (var i = this.length; i < n; i++) {
result = fn.call(scope, result, this[i], i, this);
}
return result;
}
/*
*@desc:功能类似于reduce 但是从后遍历
*/
Array.prototype.reduceRight = function (fn,lastResult,scope) {
var array = this.concat().reverse();
return array.reduce(fn, lastResult, scope);
}

常用的js数组方法

/*
*@desc:判定数组是否包含指定目标
*/
function contains(target, item) {
return target.indexOf(item) > -1;
}
/*
*@desc:移除数组中指定位置的元素,返回布尔表示成功与否
*/
function removeAt(target, index) {
return !!target.splice(index, 1).length;
}
/*
*@desc:移除数组中第一个匹配传参的那个元素
*/
function remove(target, item) {
var index = target.indexOf(item);
if (~index) {
return removeAt(target, index);
}
return false;
}
/*
*@desc:对数组进行洗牌
*/
function shuffle(target) {
var j, x, i = target.length;
for (; i > 0; j = parseInt(Math.random() * i), x = target[--i], target[i] = target[j], target[j] = x) {
}
return target;
}
/*
*@desc:从数组中随机抽选一个元素出来
*/
function random(target) {
return target[Math.floor(Math.random() * target.length)];
}
/*
*@desc:对数组进行平坦化处理,返回一个一维新数组
*/
function flatten(target) {
var result = [];
target.forEach(function (item) {
if (Array.isArray(item)) {
result = result.concat(flatten(item));
} else {
result.push(item);
}
});
return result;
}
/*
*@desc:对数组进行去重操作,返回一个没有重复元素的新数组
*/
function unique(target) {
var result = [];
loop: for (var i = 0, n = target.length; i < n; i++) {
for (var x = i + 1; x < n; x++) {
if (target[x] === target[i]) {
continue loop;
}
}
result.push(target[i]);
}
return result;
}
/*
*@desc:过滤数组中的null和undefined 但不影响原数组
*/
function compact(target) {
return target.filter(function (el) {
return el != null;
});
}
/*
*@desc:取得对象数组的每个元素的指定属性 组成数组返回
*/
function pluck(target, item) {
var result = [], prop;
target.forEach(function (item) {
prop = item[name];
if (prop != null) {
result.push(prop);
}
});
return result;
}
/*
*@desc:根据指定条件(如回调或对象的某个属性)进行分组,构成对象返回
*/
function groupBy(target, val) {
var result = {};
var iterator = $.isFunction(val) ? val : function (obj) {
return obj[val];
};
target.forEach(function (value, index) {
var key = iterator(value, index);
(result[key] || (result[key] = [])).push(value);
});
return result;
}
/*
*@desc:根据指定条件进行排序
*/
function sortBy(target, fn, scope) {
var array = target.map(function (item, index) {
return {
el: item,
re: fn.call(scope, item, index)
};
}).sort(function (left, right) {
var a = left.re, b = right.re;
return a < b ? -1 : a > b ? 1 : 0;
});
return pluck(array, 'el');
}
/*
*@desc:对两个数组取并集
*/
function union(target, array) {
return unique(target.concat(array));
}
/*
*@desc:对两个数组取交集
*/
function intersect(target, array) {
return target.filter(function (n) {
return ~array.indexOf(n);
});
}
/*
*@desc:对两个数组取差集
*/
function diff(target, array) {
var result = target.slice();
for (var i = 0; i < result.length; i++) {
for (var j = 0; j < result.length; j++) {
if (result[i] === array[j]) {
result.splice(i, 1);
i--;
break;
}
}
}
return result;
}
/*
*@desc:返回数组中的最小值(用于数字数组)
*/
function min(target) {
return Math.min.apply(0, target);
}
/*
*@desc:返回数组中的最大值(用于数字数组)
*/
function max(target) {
return Math.max.apply(0, target);
}

其实还有很多。。。

本文中的方法是根据《JavaScript框架设计》中第三章--数组的扩展与修复进行整理的。

如果您觉得本篇博文对您有所收获,觉得小女子还算用心,请点击右下角的 [推荐],谢谢!

从js的repeat方法谈js字符串与数组的扩展方法的更多相关文章

  1. js中字符串和数组相互转化的方法

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #e4af0a } p. ...

  2. 16 (H5*) JS第6天 日期、字符串、数组

    目录 1:date 2:格式化日期 3:字符串 4:字符串的方法 5:字符串的案例 6:数组的方法 7:包装类型 复习 正文 1:日期:date <script> //创建实例对象 // ...

  3. js判断数字、整数、字符串、布尔,特殊方法

    整数: function isInteger(obj) { return Math.floor(obj) === obj } isInteger(3) // true isInteger(3.3) / ...

  4. JavaScript字符串、数组、对象方法总结

    字符串方法 示例字符串: const str = "hello,kitty,hello,vue "; 一.基本方法 charAt(n) 返回指定索引的字符 charCodeAt(n ...

  5. JavaScript:记录一些字符串和数组常用的方法

    字符串: 字符串的方法:注意:都不会改变原来的字符串,返回值为新的字符串.如果(1,2),一般是包含小标1,不包含下标2 str.charAt(i): 取str的第i+1个字符,类似数组的arr[i] ...

  6. PPK谈JS笔记第一弹

    以下内容是读书笔记,再一次温习JS好书:PPK谈JS window.load=initializePageaddEventSimple('window','load',function(){}) lo ...

  7. Js 数组的各种方法及操作

    一.数组去重 var arr = [0,1,20,3,0,45,6,0]; Array.prototype.unrepeat = function(){ var array = []; for(var ...

  8. ES6 模版字符串及常用的es6扩展方法

    1.ES6 模版字符串es6 模版字符串主要用于简化字符串的拼接 <script type="text/javascript"> let obj={name:'rdb' ...

  9. javascript字符串与数组转换汇总

    本文给大家分享的是Js中字符串转换成数组,数组转换成字符串的函数,十分的简单实用,有需要的小伙伴可以参考下. 数组转字符串 1.join()方法 ? 1 2 3 4 var s= ["a&q ...

随机推荐

  1. sublime修改字体大小

    /Packages/Theme\ -\ Default/Default.sublime-theme { "class": "label_control", , ...

  2. usb驱动开发2之代码地图

    USB只是Linux庞大家族里的一个小部落,host controller是它们的族长,族里的每个USB设备都需要被系统识别.下图显示包含一个USB接口的USB鼠标导出的结果. USB系统中的第一个U ...

  3. no2.crossdomain.xml批量读取(待完善)

    读取太多url有问题 #coding=utf-8 import urllib import requests import sys import re import time def getxml(u ...

  4. Enabling CORS in WCF

    Introduction This is an intermediate example of WCF as REST based solution and enabling CORS access, ...

  5. 爬取熊猫TV,javascript,selenium,模拟点击

    from selenium import webdriver import csv def get_pages_numger(browser): res = browser.find_elements ...

  6. CSS 实现加载动画之八-圆点旋转

    这篇文件介绍的动画是QQ邮箱APP里的加载动画,效果类似,但是不完全一样.实现过程不复杂,这里不详细解释了,直接上源码.另外还有一种实现方式,利用元素的3D转换加平移. 1. 先看截图 2. 源代码 ...

  7. Enfold主题详解与实例视频教程 WordPress建站视频教程

    ENFOLD主题功能强大,同样的设置也相对较复杂,希望您在学习过程中也能多多加以练习.Enfold主题介绍:目前在ThemeForest网站,Enfold在WordPress主题销售排行中第2名,可见 ...

  8. 虚拟机安装Mac OS X ----- VM12安装Mac OS X

    Windows下虚拟机安装Mac OS X -– VM12安装Mac OS X 10.11 随着Iphone在国内大行其道,越来越多的开发者涌入iOS开发大军 中,但都苦于没有苹果机,本文即将介绍WI ...

  9. 20145222黄亚奇《Java程序设计》第2周学习总结

    教材学习内容总结 类型: 整数:short(占2字节).int(4).long(8). 浮点数:float(4).double(8) 字符:char(2) 布尔:boolean类型表示true与fal ...

  10. openssl实践总结

    openssl实验总结 OPENSSL简介 OpenSSL项目是一个协作开发一个健壮的,商业级的,全功能的,并且开放源代码工具包,它实现了安全套接字层(SSL v2/v3)和传输层安全(TLS v1) ...