5、
RegExp类
现在要介绍的内容不完全与RegExp类有关,他几乎包含了正则表达式的大部分的基本知识点和含义,但是我无意扩展出来说,如果对此感兴趣,推荐些教程和好书。以下推荐绝非随机、随意。
《精通正则表达式》,该书的作者和译者都对正则表达式有十分深厚的功底和理解,同时该书也是我目前为止见到的最好的教材,而且不用担心你的英文不好,该书的中文版翻译质量绝对一流。不过,这本书正如书名一样,是给对正则有兴趣,且真心的希望有所精通的人看的。
blog.csdn.net/lxcnn。该博客绝对是当今中国数一数二的关于正则方面的精品,博主的造诣绝不含糊,且文笔和内容也十分值得大家一看的。
《正则表达式傻瓜书》,该书的作者即《精通》一书的译者,有幸翻阅了该书的样章,书中的内容深浅合宜,语言精炼,加之作者深厚的功底,书的质量不言而喻。虽然该书尚未出版,但是绝对的值得期待。
《正则表达式必知必会》,该书短小易懂,适合不大希望精通于此,仅限于能用即可的朋友阅读,该书中有许多实例,很多内容大家甚至可以拿来就用,只是受制于其篇幅,该书不大适合进阶阅读。
如果你对以上的珍品不感兴趣,那么下面的内容希望你能耐心的看下去,我会尽我所能来让你有所收获。
正
则表达式通常用于查找、验证、替换字符串内容。其便捷和高效致使它渐渐的为大家所接收和喜爱,我想很多看到这里的朋友可能会有这样的感受:“每次用到的时
候我都会翻一遍正则的简明教程或手册,但是总是记不住,而且当有一天翻自己所写的正则时,会看不懂。”。那么没关系,记不住是因为你没有深入的去了解和思
考它,我不会穷举每一个元字符和语法结构,尽量让它变得有那么一点意思。
案例一、验证一个字符串由8到16位数字、英文字母、下划线组成。
这个验证是最基本且最常用的,验证的首要条件是限制死首和尾,即正则必须匹配整个字符串,从起始字符一直到结尾字符。先看正则
/
^
[
\d
a-zA-Z_]
{8,16}
$
/
这个正则中没有任何的空白,两个/之间的内容就是正则表达式,在JavaScript中我们有两个方式创建正则表达式对象,上面的是字面量对象,另外一个是构造函数方法,即
-
var
reg =
new
RegExp(
"^[\\da-zA-Z_]{8,16}$"
,
"mode"
);
关于模式,有g、i、m三个,i表示忽略大小写,g和m会在后面深入解析,因为简单的说个一两句不会太容易理解。
两者效果几乎等效,而字面量方式简洁的许多,细心的你一定看到后一种方法中\d前多了一个\。原因是字符串中\x会被当作转义字符进行转义。
接下来看蓝色部分,^和$符号分别代表字符串的开始和字符串的结尾,但是在m模式的时候他们的含义会有不同,在m模式下,他们分别代表行首和行尾。
[]
之间的是字符集合,这相当于字符的switch,[^...]则是匹配非集合。这个很好理解,在你看过的任何一篇教程中都不会漏下它,不过你一定想知道匹
配不等于某个字符串的字符串该怎么办,答案是否定环视(断言、预查,以下统一称为环视),一会在介绍环视时,我们再来介绍。
{8,16}表示一个范围量词,他表示匹配之前的分组或字符重复多少次。与之相对应的还有+,*,?,{m,},{,n}等。
案例二、验证一个有数字、字母组成的8-12位字符串。必须包含至少一个数字和字母。
这个与案例一有点区别,那就是最后一句的限制,所以我们需要引入一个判断逻辑,那就是环视,先引入环视的概念和解释吧^_^。
环
视从方向来说分为逆序和顺序,从逻辑来说分为肯定和否定。不过JavaScript正则表达式不支持逆序的环视,只支持顺序肯定环视、顺序否定环视。环视
有个特点就是不占据所匹配字符,所以他会预先进行一次匹配,然后匹配完了之后会回溯会环视匹配之前的位置。让我们看刚才的案例吧。首先进行2次否定环视,
分别排除掉纯粹由数字或由字母组成的字符串。然后再把案例一的正则表达式放进来就可以了。如下
/^(?!\d+$)(?!\D+$)[a-zA-Z\d]{8,12}$/
假
设字符串为abcdefg123。那么匹配的过程如下。首先^匹配字符串开始,接着是第一个否定环视,(?!\d+$)他从'a'开始匹配,\d+即不能
匹配,匹配失败,否定环视成功,接下来匹配(?!\D+$),\D表示非数字,那么从a-g都可以匹配,接下来是1,\D+匹配完成,如果没有$那么这个
匹配其实也算成功,但是\D+匹配完成之后有一个$,那么$匹配1失败。否定环视成功,此时字符串位置回到a之前。开始后面的匹配。[a-zA-Z\d]
{8,12}匹配abcdefg123成功,具体过程忽略,然后把句柄交给$,匹配成功。此时整个匹配成功。因为篇幅和表述能力问题,关于环视的解释不够
清晰,如果至此你依然没有弄清。那么请访问过客的相关博客,真的很棒(
blog.csdn.net/lxcnn
)。
好吧,我们现在倒回来看一些日常应用中的一些误解导致的错误应用。
1、
包含字母数字的字符串判断使用\w是不对的。因为\w<==>[a-zA-Z0-9_],所以使用时请注意
2、
JavaScript中不支持逆序环视。无论是肯定还是否定,因此如果其他语言的程序员在使用js正则的时候千万要注意
3、
.元字符在字符组中是普通字符,而不解释为任意字符的元字符,同时.元字符不匹配\n(换行符),JavaScript中没有单行模式以使.匹配\n。
4、
在使用test、exec时一定要弄清楚g模式之后再使用。因为一旦使用了g模式,那么会保存全局的lastIndex,在你下一次进行匹配时是从lastIndex开始,而非字符串首。(感谢过客之前对此的解释和指导。有兴趣的可以看这个帖子,看过客的解释
http://topic.csdn.net/u/20110117/18/e2423564-856b-4f46-8879-0c382a3e1c7a.html?93335
)。在这里我把其中的例子发出来,让大家有个了解,请看:
-
var
arr = [ 1 , 2 , 3 , 4 , 5 ];
-
var
reg = /^\d+$/g ;
-
for
(
var
i = 0 ; i < arr . length ; i ++){
-
alert ( reg . test ( arr [ i ]));
-
}
5、
js正则不支持命名分组,所以后向引用的时候要格外注意分组的序号。
6、
js正则不支持固话分组和占有优先量词。所以如果可以的话,[^xx]+取代.+?来使用,一方面可以提高效率,另一方面可以减少错误的匹配结果。
7、
正则效率上,new RegExp()与字面量方式创建没有区别,而使用变量保存一个正则对象和循环中使用同一个正则表达式字面量效率上也没区别(至少在大部分的浏览器上是这样的)。
8、
在使用new RegExp()创建正则的时候,切记转义问题。new RegExp("\\d")才等价于/\d/,使用new RegExp("\d")就会得到错误的正则。
9、
回溯和环视是2个非常重要的概念,同时也要弄清楚位置和字符的区别。时间和能力的原因,推荐移步过客的博客(
http://blog.csdn.net/lxcnn/archive/2009/06/28/4304754.aspx
和
http://blog.csdn.net/lxcnn/archive/2009/06/28/4304651.aspx
)
关于正则目前仅仅只提这些,因为后面准备了一个实战博客,那个时候会详细介绍几个实用的实例以及推导过程。下面看看在介绍字符串的时候落下的几个方法。replace/match/search,OK,我们来一个一个看吧
replace方法是提供强大的替换功能,他不仅能够替换简单的文本。还能使用一个替换函数来进行更复杂的替换,请看下面的代码:
-
var
str =
"dream on, dream on, dream on,dream yourself a dream come true.dream on, dream on, dream on,"
;
-
var
reg = /dream/g ;
-
var
i = 0 ;
-
alert ( str . replace ( reg , function
( m ){
-
return
m + ( i ++). toString ();
-
}));
该方法通过一个匿名方法,将查找到的dream单词进行替换,该替换会给后面的dream单词添加一个序列。你可能会想到下面的方法:
-
var
str =
"dream on, dream on, dream on,dream yourself a dream come true.dream on, dream on, dream on,"
;
-
var
reg = /(dream)/g ;
-
var
i = 0 ;
-
alert ( str . replace ( reg , "$1"
+ i ++));
可惜很遗憾你运行一下就会发现每次都是0。这点在任何可以使用委托方法(匿名方法、函数指针==)进行替换的语言中都是一样的,这个和替换机制是有关的。
replace的时候非正则替换有个缺陷,就是只会替换第一个。相当于没有加上g模式的正则。所以使用的时候一定要注意,当然在替换的时候不要忘了g模式哟。
match
则是查找匹配的方法,他同样支持正则表达式作为查找模式,不过有一点需要注意,如果使用全局检索(g模式)的时候,返回的是一个数组,该数组不包括分组信
息。而如果不使用全局检索(g模式)的时候,返回的是第一个匹配的文本,以及各分组的匹配内容。比如下面的代码:
-
var
str =
"dream on, dream on, dream on,dream yourself a dream come true.dream on, dream on, dream on,"
;
-
var
reg = /(dream)[^,]+/ ;
-
alert ( str . match ( reg ));
-
reg = /(dream)[^,]+/g ;
-
alert ( str . match ( reg ));
最后一个是search,他接收一个正则对象,他返回search到的第一个匹配文本的起始位置,该方法不受g模式的影响。
-
var
str =
"dream on, dream on, dream on,dream yourself a dream come true.dream on, dream on, dream on,"
;
-
reg = /dream/g ;
-
alert ( str . search ( reg ));
-
alert ( str . search ( reg ));
-
alert ( str . search ( reg ));
该方法三次alert出的都是0。其实还有一个split方法也支持正则。不过它很简单,在这里不再提了。
RegExp有以下的属性需要记住,lastIndex是最后一次匹配的位置(还记得g模式么),source是正则表达式的源文本,而$1、$+、$$等意味著什么请可查看下手册,这里就不一一列举了。
6、
Global对象
这里没有用类这个名词,是因为连这个关键字实际上都不存在,在JavaScript中所有的函数都是对象的方法,所以你看到的所有内置的“函数”其实都是全局对象的方法。
编码、解码方法,对uri进行编码是为了使防乱码的一个有效措施,很多后台语言也都有相对应的解码、编码方法。
encodeURI/encodeURIComponent/decodeURI/decodeURIComponent。
如果不能区分其中的区别,那么用后者代替前者吧。
escape/unescape基本上不推荐使用,用上面的方法来取代吧。
类
型转换的方法也是比较常用的方法。比如Number、String方法,但是看似简单的2个方法还有真点需要补充的。Number方法不能取代
parseInt和parseFloat方法,因为Number方法只能把真正的数字转换为数字(该方法用来验证一个输入是否是数字很好吧)。先看这4句
代码。
-
alert ( Number (
'01x'
));
-
alert ( Number ( '011'
));
-
alert ( String ( 0X11 ));
-
alert ( String ( 011 ));
其
实关于这点我在之前的博客提到过,现在再拿出来解释下。第一个如果用parseInt会得到1,而用Number强转将返回NaN。千万要使用isNaN
来判断是否成功转换,而不是Number('01x').constructor == Number。因为NaN是个数字类型,但是他的意思是
Not a Number。第二个返回的是11,看上去很正常啊?可是011往往可能意味着是8进制的数哦。所以字符串形式的011和数字型的011可不
是一个意思哦。所以在使用数字字面量的时候注意前置0的使用。第三行返回的是17,为什么?刚才提到过0X11是16进制的数字,那么他翻译为17就意味
着转换为string类型前会强转为10进制数,第三行同理。那么第三行想输出11怎么办呢,使用它:(0x11).toString('16'),8进
制也一样哦。所以转换的时候要了解清楚先。
最
后一个要说的是最有争议的eval方法。他的功能十分强大,但是缺点也异常明显,代码不易读、性能低下、安全性降低。所以一般情况下可以用
setTimeout、setInterval、数组等方法来替代。注意在处理json的时候要把json包括在一个括号里
哦:eval('(' + jsondata + ')');
相关推荐
1. **Object对象**:所有JavaScript对象的基类,提供了检查和操作对象的方法。例如: - `constructor`:指向创建对象的函数。 - `hasOwnProperty()`:判断对象是否直接拥有某个属性,而非从原型链中继承。 - `...
首先,手册的前几章会介绍JavaScript对象的基础知识,包括对象的创建、属性和方法的定义,以及对象与数据类型的关联。JavaScript中的对象是基于原型的,这意味着它们可以通过原型链共享属性和方法。此外,还会讲解...
2. **原型(Prototype)**:JavaScript中的每个对象都有一个内置的`__proto__`属性,指向其构造函数的原型对象。原型对象可以包含共享的方法和属性,使得实例可以访问。我们也可以通过`prototype`属性来修改构造函数...
1. **全局对象Global**: JavaScript中的全局对象提供了许多内置函数,如`Math`(数学运算)、`Date`(日期和时间操作)、`JSON`(JSON解析和序列化)等。全局变量默认会成为全局对象的属性。 2. **对象创建与原型...
这意味着对象可以直接从其他对象继承属性和方法,而不是从类实例化。JavaScript的类型系统包括五种基本类型:undefined、number、boolean、string和function,以及一种复合类型:object。其中,function作为第一类...
4. **第4章 JavaScript基于对象编程**:JavaScript是一门面向对象的语言,这一章会讲解对象的概念、创建对象的方法(如字面量语法和构造函数)、原型链、继承以及封装和多态等面向对象特性。 5. **第5章 文档对象...
核心部分主要包括 JavaScript 的数据类型、运算符、表达式,以及 JavaScript 中的内置的全局对象、全局属性和全局函数等。浏览器对象模型提供了用户与浏览器之间的交互的对象以及操作的接口。文档对象模型是由 W3C ...
- JavaScript对象都有一个内置的`__proto__`属性,指向其构造函数的原型。原型是一个对象,可以包含共享的属性和方法。原型链允许对象访问其构造函数原型上的属性和方法。 - 使用`Object.prototype.isPrototypeOf...
JavaScript有全局对象、内置对象、宿主对象等层次结构,如DOM(文档对象模型)和BOM(浏览器对象模型)。 8.3.2 客户端对象层次介绍 客户端对象层次主要涉及浏览器提供的对象,如window、document等。 8.3.3 ...
JavaScript对象定义是编程语言中的核心概念,它在Web开发中起着至关重要的作用。JavaScript是一种基于原型的对象导向语言,它的对象定义方式具有独特的灵活性。在本文中,我们将深入探讨JavaScript对象的定义、创建...
在现代Web开发中,JavaScript作为一种脚本语言,其核心能力之一就是面向对象编程(OOP)。面向对象编程是一种编程范式,它使用“对象”来设计软件。对象可以包含数据,以属性的形式表示,也可以包含代码,以方法的...
- **类与对象**:JavaScript没有内置的类的概念,但在ES6中引入了`class`关键字来模拟类的行为。对象则是由类实例化出来的具体实体。 - **封装**:封装是指将数据和操作这些数据的方法绑定在一起,隐藏内部状态,只...
JavaScript是一种广泛应用于Web开发的动态、弱类型的语言,它的面向对象编程能力是其核心特性之一。面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它基于“对象”的概念,允许程序员创建数据...
本小册"JavaScript对象经典小册 chm"深入探讨了JavaScript中的核心概念——对象和数组,旨在帮助开发者更好地理解和掌握这些基础知识。 一、JavaScript对象 1. 对象概述:JavaScript对象是一种数据结构,它由键值对...
#### 一、JavaScript对象的基础概念 在JavaScript中,对象是一种非常重要的数据类型,它能够存储键值对的形式来表示复杂的结构数据。这些键通常被称为属性名,而对应的值则称为属性值。除了作为数据容器外,...
JavaScript是一种广泛应用于Web开发的脚本语言,尤其在构建交互式网页和动态应用程序时不可或...通过阅读和实践这些案例,你可以逐步掌握如何创建、继承和操作JavaScript对象,从而成为一名更出色的JavaScript开发者。
### JavaScript 快速入门教程与面向对象编程 #### 一、概要 JavaScript 是一种广泛应用于网页开发中的脚本语言,具有轻量级、解释型等特点。它可以在客户端执行,无需服务器支持,使得网页能够更加动态和交互。 ##...