`
driftcloudy
  • 浏览: 132212 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【翻译】JS里的各种trim实现

阅读更多

前不久blog频道有人发表了一篇讲js里各种trim实现的 http://justjavac.iteye.com/blog/933093

不过没有提及Dojo中的trim。Dojo中有两种trim实现:

 

1.较为常用的:

dojo.trim = String.prototype.trim ?
		function(str){ return str.trim(); } :
		function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };

 

2.速度最快但是实现较为复杂:

dojo.string.trim = String.prototype.trim ?
	dojo.trim : // aliasing to the native function
	function(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;
	};

 

第一种实现位于dojo base中,是dojo针对JS缺陷做出的一种弥补,也是dojo里最经常被调用到的trim。

第二种实现位于dojo.string中,是dojo里string工具类的方法。这种实现比较诡异,也很有趣。

另外在Dojo注释里看到有关各种trim方法的对比的文章,故将其翻译下来,原文地址:Faster Javascript Trim

 

Faster JavaScript Trim

js中并没有自带trim方法,但是该方法被无数的JS库实现了,并且通常都是将trim置为全局函数、或者将trim作为String.prototype 的方法。然而,我从没见到过一种 trim实现能够充分发挥出它的效率,毕竟,大多数的程序员并不了解正则表达式的性能问题(我就是= =!)。

 

当看到那些极为糟糕的trim实现之后,我决定研究一下如何编写出高效率的trim。在正式进入分析之前,先来看一下结论:

Method Fifox2 IE6
trim1 15ms <0.5ms
trim2

31ms

<0.5ms
trim3 46ms 31ms
trim4 47ms 46ms
trim5 156ms 1656ms
trim6 172ms 2406ms
trim7 172ms 1640ms
trim8 281ms <0.5ms
trim9 125ms 78ms
trim10 <0.5ms <0.5ms
trim11 <0.5ms <0.5ms

Note1: 这里的比较结果是在作者的电脑上对Magna Carta (over 27,600 characters) 运行20次trim之后得出的

Note2: trim4和trim6是JS库中最经常使用的实现方式

Note3: 前文说的极为糟糕的trim实现并不在上面11种trim里,但在文章的末尾会提到。

 

The analysis

JS里的trim可能有很多种实现方式,上表的11种是最显著的。这里所作的分析都是基于FF2.0.0.4和IE6。(太老了,不过在天朝,研究IE6还是有意义的)

 

Trim1:

return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');

如果考虑各种情形,这也许就是最好的一种trim实现了。trim1在处理长字符串时速度优势非常显著。速度在很大程度上取决于这里的两个regexp触发的js正则引擎优化。

 

Trim2:

return str.replace(/^\s+/, '').replace(/\s+$/, '');

非常类似于trim1,但是速度稍慢,因为它不会触发一些优化。

 

Trim3:

return str.substring(Math.max(str.search(/\S/), 0), str.search(/\S\s*$/) + 1);

trim3通常比下面的trim快,但是比trim1和trim2慢。(Its speed comes from its use of simple, character-index lookups.不懂...)

 

Trim4:

return str.replace(/^\s+|\s+$/g, '');

这是一种较为简单的实现,因而被广泛用在各种js库里。如果作用于短字符串,而且没有头部空白或者尾部,trim4会是最快的。 这种速度上的优势部分来自于它触发了initial-character discrimination optimization 。如果是作用于长字符串,那么它比trim1-3慢,因为最高级别的‘alternation ’(即该regexp里有个或)阻碍了一些优化。

 

Trim5:

str = str.match(/\S+(?:\s+\S+)*/);
return str ? str[0] : '';

如果是作用在空字符串或者仅仅包含空格(“whitespace-only”) 的字符串上,trim5的速度可能会最快,因为它会触发一些pre-check of required character 的优化。注意,在IE6下该方法针对长字符串会非常的慢。

 

Trim6:

return str.replace(/^\s*(\S*(\s+\S+)*)\s*$/, '$1');

这也是一种比较普遍的做法,被一些牛逼的js code所推广。它和trim8很相似,但没有好的理由去用它,特别是它在IE6下会非常的慢。

 

Trim7:

return str.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, '$1');

和trim6基本相同,唯一的区别就是trim7用了一个非捕获性分组(IE5.0及以下不支持)。同样,在IE6下会非常慢。

 

Trim8:

return str.replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');

trim8使用了简单、一趟(因为用了?)、贪婪的匹配方式。trim8在IE6下会特别特别快。说明IE会针对 "any character" tokens做一些超级优化。

 

Trim9:

return str.replace(/^\s*([\S\s]*?)\s*$/, '$1');

如果作用于非常短的字符串,而且字符串包含非空格字符以及边缘是空格,那么trim9将会非常快。这种性能上的优势是由于它使用了简单的、一趟、惰性贪婪匹配。同trim8,trim9在IE6下速度也远快于FF。

 

 

下面我在一个JS库里的实现看到的trim实现,列出来做一个警示

return str.replace(/^\s*([\S\s]*)\b\s*$/, '$1');

该方法有时是最快的,比如是作用在短字符串,而且该字符串包含非空格字符以及边缘是空格。但如果是长字符串,里头有很多单词的边界,它的性能就很差了。如果是仅仅由空白字符组成的长字符串,它的性能将无比糟糕(since that triggers an exponentially increasing amount of backtracking)。不要使用这种实现!

 

A different endgame

上面表格中的11种trim尚有2种还没涉及。这2种方法采用的是非正则表达式、正则与非正则混合的方法。

 

经过比较和分析后,我想尝试一下如何用非正则表达式去实现一个trim:

 

Trim10:

function trim10 (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.charAt(i)) === -1) {
			str = str.substring(i);
			break;
		}
	}
	for (i = str.length - 1; i >= 0; i--) {
		if (whitespace.indexOf(str.charAt(i)) === -1) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
} 

它的表现如何呢?如果是针对长字符串,并且头部尾部不包含过多的空白,该方法会轻松的战胜上述的9种trim(除了IE中的trim1/2/8,它们快的太离谱了)

 

这是否意味着FF里的正则表达式很慢?一点也不。这里的问题在于,尽管正则表达式非常适用于去除头部的正则表达式,但是它们并没有一个合适的方式去跳转到字符串的末尾。然而trim10却可以做到,它的第二个for循环直接从字符串的末尾开始处理。

 

知道了这点,那么不如去创造一种正则和非正则的混合实现,它既有正则表达式在处理字符串开头空白的性能,又有非正则表达式在处理字符串末尾空白的速度优势。

 

Trim11:

function trim11 (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;
}

虽然trim11在处理有些字符串的时候比trim10慢,但是它任然速度飞快,并且使用了更少的代码。而且,如果处理的字符串在开头有大量的空白(包含直接由空白组成的字符串),那么trim11的速度将会明显比trim10快。

 

In conclusion…

由于不同浏览器的区别,处理的也是不同类型的字符串,因此没有一种trim方法总是表现的比其他所有都快。这里我有一个一般的建议:

  • 使用trim1 如果你想获得一个比较快的速度,并且能跨浏览器使用
  • 使用trim11 如果你想在不同的浏览器中快速的处理长字符串

如果你想自己测测上述所有trim方法的性能,那么尽量按照我的适用建议。后台处理可能使得某一次的测试结果极为不准确,因此建议测试很多次,并且仅仅取跑的最快的一些结果。

 

最后一点建议,虽然很多人喜欢缓存正则表达式,比如将它们作为全局变量存储起来,这样以后就不要重复编译了。但是这对trim方法来说意义不大。另外一些浏览器会自动的缓存正则表达式,所以在一些不包含其它regexp的循环里使用trim,浏览器实际上并不会去重复的编译。

 

better trim

写完这些不久我就意识到trim10/11可以被更好的改写。trim12采用了和trim11类似的正则非正则混合的方式。

 

Trim12:

function trim12 (str) {
	var	str = str.replace(/^\s\s*/, ''),
		ws = /\s/,
		i = str.length;
	while (ws.test(str.charAt(--i)));
	return str.slice(0, i + 1);
}
 

 

 

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

 

去蝴蝶书上查了下,Javascript中的“ \s ”相当于“ [ \f \n \r \t \u000B \u0020 \u00A0 \u2028 \u2029 ] ”

其中:

\f             换页符

\n            换行符

\r             回车符

\t             tab符

\u000B    垂直定位符

\u0020    空格

\u00A0    非中断空格

\u2028    行分隔符

\u2029    段落分隔符

 

根据Ecma-262 3rd 中描述:

 

 

 

1
9
分享到:
评论

相关推荐

    js 自定义trim去除字符串左右杂质

    js 自定义trim去除字符串左右杂质 在 Java 中,String 类型提供了 trim() 方法来去除字符串左右的空格。然而,在 JavaScript 中,并没有提供类似的方法来去除字符串左右的杂质。因此,我们需要自定义 trim() 方法来...

    js设置兼容trim函数

    ### js设置兼容trim函数 #### 知识点一:JavaScript中的`trim()`方法 `trim()` 方法用于删除字符串两端的空白字符(包括空格、制表符、换页符等)。此方法不会改变原始字符串,而是返回一个新的字符串。 **语法**...

    javascript自定义trim()方法

    然而,为了方便开发者处理字符串,本文将详细介绍如何在JavaScript中自定义实现`trim()`方法。 #### 自定义`trim()`方法 在JavaScript中,可以通过编写简单的函数来自定义实现`trim()`方法。下面将分步骤详细介绍...

    javascript trim函数

    javascript trim函数。在javascript中,对于字符串可以使用trim去除末尾和开头的多余空白字符。 方法有两种,分别是普通字符串处理法和正则表达式法。根据需要自选。

    Javascript中实现trim函数的两种方法.docx

    ### JavaScript中实现trim函数的两种方法 在日常的前端开发工作中,我们经常需要对字符串进行操作,其中一种常见的需求就是去除字符串两端的空白字符。尽管现代JavaScript已经内置了`trim()`方法来帮助开发者轻松...

    js_trim()十二种实现.txt

    ### js_trim()十二种实现详解 #### 概述 在前端开发中,字符串处理是非常常见的需求之一,其中去除字符串首尾空白字符的功能尤为重要。本文将详细介绍十二种不同的`js_trim()`实现方法,并对每种方法的性能进行...

    js trim 函数

    javascript 的 trim 函数的实现,去掉字符串的左右空格,由于只使用了String的原生函数,没有使用正则,运算速度极快,是0毫秒级别的,推荐大家使用.

    js-trim()方法IE无效的解决办法

    ### js-trim()方法IE无效的解决办法 在JavaScript中,`trim()`方法主要用于去除字符串首尾的空白字符。此方法在现代浏览器中通常能够很好地工作,但在Internet Explorer(IE)的一些版本中可能存在兼容性问题。这是...

    Javascript中各种trim的实现详细解析

    这是lgzx公司的一道面试题,要求给js的String添加一个方法,去除字符串两旁的空白字符(包括空格、制表符、换页符等)。 代码如下:String.prototype.trim = function() { //return this.replace(/[(^\s+)(\s+$)]/g,...

    C语言实现trim函数

    C语言实现trim函数,函数名:trim,参数:源字符串、目的字符串...

    js代码-trim方法实现

    JavaScript中的`trim()`方法是一个非常实用的字符串处理函数,它用于去除字符串两端的空白字符,如空格、换行符等。在JavaScript编程中,处理用户输入或从API获取的数据时,经常需要对字符串进行清洗,`trim()`方法...

    trimssd Xp实现trim

    TrimSSD是一款可以在任何Windows操作系统对SSD进行TRIM操作的软件 支持重启后对系统盘进行TRIM操作。 速度超快,完胜任何同类软件。 仅支持NTFS文件系统,暂不支持FAT32。 WindowsXP M4-128G 测试通过。

    java实现的翻译功能

    首先,实现翻译功能的关键在于接入翻译API。常见的翻译API有Google Translate API、Microsoft Azure Translator Text API、IBM Watson Language Translator等。这些API提供RESTful接口,通过HTTP请求发送待翻译的...

    Js里面给String添加trim()方法,实现去掉字符串两边空格

    原生的JavaScript自ECMAScript5标准引入后,就已经提供了`String.trim()`方法来去除字符串首尾的空白字符,这为开发者带来了极大的便利。然而,在此之前,或者在某些特定环境下(如旧版本的浏览器),`String.trim()...

    Javascript中实现trim()函数的两种方法

    在JavaScript中我们需要用到trim的地方很多,但是JavaScript又没有独立的trim函数或者方法可以使用,所以我们需要自己写个trim函数来实现我们的目的。 方案一: 以原型方式调用,即obj.trim()形式,此方式简单且使用...

    Trim()的含义

    其中,`Trim()`函数作为字符串操作的基础工具,在各种编程语言中都有着广泛的应用。本文将围绕“Trim()的含义”这一主题,深入探讨`Trim()`函数的作用、应用场景以及其背后的实现原理。 #### 一、Trim()函数的基本...

    javascript的trim和日期时间格式化函数

    ### JavaScript中的Trim函数和日期时间格式化函数 在JavaScript中,字符串处理和日期操作是非常常见的需求,尤其是在数据清洗、格式转换等场景下。本文将详细介绍如何利用自定义方法实现字符串的Trim功能以及日期...

    电源模块Trim引脚的应用.pdf

    使用Trim引脚调整电压的方法非常简单,通常只需要增加一个电阻即可实现。 通过Trim引脚调节输出电压时,需要计算调节电阻的取值。调节电阻的计算依赖于电源模块内部电路的参数。文章以广州金升阳DC-DC电源模块为例...

    js代码-js trim实现

    尽管JavaScript的内置`trim`方法已经足够高效,但有时候我们可能需要自定义实现,以适应某些特殊需求或者在不支持`trim`方法的旧版浏览器中使用。一个简单的自定义`trim`函数可能如下所示: ```javascript function...

Global site tag (gtag.js) - Google Analytics