博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从js的repeat方法谈js字符串与数组的扩展方法
阅读量:6798 次
发布时间:2019-06-26

本文共 12662 字,大约阅读时间需要 42 分钟。

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一样,每种语言的代码都有些性能方面的小常识。

(有空可以看看          )

回到正题

下面来说说。。。

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:仅次于版本10function 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.powfunction pad(target, n) {    return ((1 << n).toString(2) + target).slice(-n);}//版本5:toFixedfunction 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(/
]*>([\S\s]*?)<\/script>/img, '');}/**@desc: 将字符串经过html转义得到适合在页面上显示的内容*/function escapeHTML(target) { return target.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, '$&
').replace('/>
/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

常用的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框架设计》中第三章--数组的扩展与修复进行整理的。

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

转载地址:http://rxego.baihongyu.com/

你可能感兴趣的文章
LEXUS OPENCART 自适应主题模板 ABC-0019-01 HIGHLIGHTED FEA
查看>>
设置ListView页眉注意事项
查看>>
ubuntu 更新出错
查看>>
nginx学习笔记(8)虚拟主机名---转载
查看>>
elasticsearch6 java 操作手册
查看>>
[LeetCode] Symmetric Tree
查看>>
jroo国际化实现方式
查看>>
【学习笔记3】解决struts2配置文件无提示问题
查看>>
设计模式学习笔记之单例模式(Java实现)
查看>>
hbase并发问题
查看>>
php下载文件
查看>>
Kurento Modules
查看>>
多种控制器的创建方式
查看>>
NSUserDefaults 简介,使用 NSUserDefaults 存储自定义
查看>>
IDEA_15构建SSM登录功能(1)
查看>>
Linux就是这个范儿
查看>>
基于JSTL自定义标签库
查看>>
hibernate里使用JDBC查询示例代码
查看>>
关闭tomcat命令窗体
查看>>
使用hive的常用命令语句
查看>>