从js的repeat方法谈js字符串与数组的扩展方法
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, '&')
.repeat(/</g, '<')
.repeat(/>/g, '>')
.repeat(/"/g, '"')
.repeat(/'/g, ''');
}
/*
*@desc: 将字符串中的html实体字符还原为对应字符
*/
function unescapeHTML(target) {//
return target.repeat(/</g, '<')
.repeat(/>/g, '>')
.repeat(/"/g, '"')
.repeat(/&/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字符串与数组的扩展方法的更多相关文章
- js中字符串和数组相互转化的方法
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #e4af0a } p. ...
- 16 (H5*) JS第6天 日期、字符串、数组
目录 1:date 2:格式化日期 3:字符串 4:字符串的方法 5:字符串的案例 6:数组的方法 7:包装类型 复习 正文 1:日期:date <script> //创建实例对象 // ...
- js判断数字、整数、字符串、布尔,特殊方法
整数: function isInteger(obj) { return Math.floor(obj) === obj } isInteger(3) // true isInteger(3.3) / ...
- JavaScript字符串、数组、对象方法总结
字符串方法 示例字符串: const str = "hello,kitty,hello,vue "; 一.基本方法 charAt(n) 返回指定索引的字符 charCodeAt(n ...
- JavaScript:记录一些字符串和数组常用的方法
字符串: 字符串的方法:注意:都不会改变原来的字符串,返回值为新的字符串.如果(1,2),一般是包含小标1,不包含下标2 str.charAt(i): 取str的第i+1个字符,类似数组的arr[i] ...
- PPK谈JS笔记第一弹
以下内容是读书笔记,再一次温习JS好书:PPK谈JS window.load=initializePageaddEventSimple('window','load',function(){}) lo ...
- Js 数组的各种方法及操作
一.数组去重 var arr = [0,1,20,3,0,45,6,0]; Array.prototype.unrepeat = function(){ var array = []; for(var ...
- ES6 模版字符串及常用的es6扩展方法
1.ES6 模版字符串es6 模版字符串主要用于简化字符串的拼接 <script type="text/javascript"> let obj={name:'rdb' ...
- javascript字符串与数组转换汇总
本文给大家分享的是Js中字符串转换成数组,数组转换成字符串的函数,十分的简单实用,有需要的小伙伴可以参考下. 数组转字符串 1.join()方法 ? 1 2 3 4 var s= ["a&q ...
随机推荐
- sublime修改字体大小
/Packages/Theme\ -\ Default/Default.sublime-theme { "class": "label_control", , ...
- usb驱动开发2之代码地图
USB只是Linux庞大家族里的一个小部落,host controller是它们的族长,族里的每个USB设备都需要被系统识别.下图显示包含一个USB接口的USB鼠标导出的结果. USB系统中的第一个U ...
- no2.crossdomain.xml批量读取(待完善)
读取太多url有问题 #coding=utf-8 import urllib import requests import sys import re import time def getxml(u ...
- Enabling CORS in WCF
Introduction This is an intermediate example of WCF as REST based solution and enabling CORS access, ...
- 爬取熊猫TV,javascript,selenium,模拟点击
from selenium import webdriver import csv def get_pages_numger(browser): res = browser.find_elements ...
- CSS 实现加载动画之八-圆点旋转
这篇文件介绍的动画是QQ邮箱APP里的加载动画,效果类似,但是不完全一样.实现过程不复杂,这里不详细解释了,直接上源码.另外还有一种实现方式,利用元素的3D转换加平移. 1. 先看截图 2. 源代码 ...
- Enfold主题详解与实例视频教程 WordPress建站视频教程
ENFOLD主题功能强大,同样的设置也相对较复杂,希望您在学习过程中也能多多加以练习.Enfold主题介绍:目前在ThemeForest网站,Enfold在WordPress主题销售排行中第2名,可见 ...
- 虚拟机安装Mac OS X ----- VM12安装Mac OS X
Windows下虚拟机安装Mac OS X -– VM12安装Mac OS X 10.11 随着Iphone在国内大行其道,越来越多的开发者涌入iOS开发大军 中,但都苦于没有苹果机,本文即将介绍WI ...
- 20145222黄亚奇《Java程序设计》第2周学习总结
教材学习内容总结 类型: 整数:short(占2字节).int(4).long(8). 浮点数:float(4).double(8) 字符:char(2) 布尔:boolean类型表示true与fal ...
- openssl实践总结
openssl实验总结 OPENSSL简介 OpenSSL项目是一个协作开发一个健壮的,商业级的,全功能的,并且开放源代码工具包,它实现了安全套接字层(SSL v2/v3)和传输层安全(TLS v1) ...