BOM
BOM的全称叫做Browser OjbectModel 浏览器对象模型,它定义了操作浏览器的接口。
BOM对象包括:Window、History、Navigator、Screen和Location。但是由于浏览器厂商的不同,BOM对象的兼容性极低,一般情况下,我们只用其中的一部分功能。
具体请参考w3school中的介绍:
http://www.w3school.com.cn/jsref/index.asp
Navigator
navigator.userAgent是我们经常使用的属性,它可以返回客户端的代理值。用这个我们就可以判断当前用户使用的是pc端还是移动端,是什么浏览器。
Screen
screen.availHeight/availWidth 可以查看除了window任务栏之外的屏幕的高度和宽度。
screen.height/width 返回显示器的屏幕的高度和宽度。不过这个兼容的较少。
screen.deviceXDPI/deviceYDPI返回显示屏幕每英寸的水平/垂直点数,即分辨率。DPI越高,分辨率越高。
History
history.length 可以返回当前窗口查看过的网页记录的数量,即浏览历史的长度。
history.back() 可以让浏览器进入到下一个历史页面。
history.forward() 可以让浏览器返回到上一个历史页面。
history.go() 这个方法有一个参数,当参数是正数的时候,前进到下一个历史页面,当是负数的时候,回退到上一个历史页面。即前两个的综合方法。
Location
location.host 可以返回当前的主机名和当前的URL端口号。比如百度就返回www.baidu.com
location.search 设置或返回从问好开始的URL(查询部分)
location.hash 可以跳转到相应的id的元素的位置,和a标签的锚点功能差不多。可以配合css3的:target一起使用改变元素的样式。
location.reload() 方法可以重新加载当前页面
BOM就介绍这么多,大家可以看看文档学习一下其他的东西。
正则表达式
在开始讲解正则表达式之前,我们先了解一下转义字符“\”。
我们如果想要打印出来双引号,因为双引号本身是一种语法规则,所以正常情况下是打印不出来的,这个时候就需要用到转义字符“/”来把双引号转化成普通的字符而不是语法规则。
1.
2. var str = ‘\”\”‘;
3. console.log(str); // “”
转义字符配合特殊的字母有特殊的意义:
\n 代表字符串和换行
\r 代表字符串的回车
\t 代表制表符tab
等等
多行字符串
1.真正的多行字符串,在每一行最后加一个\n就可以了。
2.为了让结构看起来清晰,我们在编辑器中人为的换行,但是本身并不是多行字符串,这个时候只需要在每一行末尾加一个“\”就可以了。
1.
2. var str = ‘\
3. <div class=”demo”>\
4. <span></span>\
5. <p></p>\
6. </div>\
7. ‘
了解了转义字符之后,下面我们正式进入正则表达式部分。
正则表达式的作用
正则表达式是进行字符串匹配检测的,当我们为了匹配特殊字符或有特殊匹配原则的字符的时候,正则表达式是最佳的选择。
正则表达式(RegExp)有两种创建方式:
1.直接量
1.
2. var reg = /abc/;
2.构造函数
1.
2. var reg = new RegExp(‘abc’);
要匹配的字符串放在第一个参数,或者将一个现成的正则表达式放进第一个参数。
1.
2. var reg = /abc/;
3. var reg2 = new RegExp(reg);
修饰符
一个正则表达式有三个描述的属性g、i、m,表示三种特定的修饰功能。
1.
2. var reg = /abc/gim;
在直接量中直接在后面加上gim就可以了,但是在构造函数中,我们要把修饰符放在第二个参数上。
1.
2. var reg = new RegExp(‘abc’, ‘gim’);
这两种写出来的效果是一模一样的,但是由于构造函数书写起来太麻烦而且还需要转义字符,个人推荐用直接量来构造正则表达式。
正则表达式上面有一个方法test(),可以测试一个字符串符不符合这个匹配规则。
1.
2. var reg = /abc/g;
3. console.log(reg.test(‘abcabc’)); // true
这样就实现了一个最基本的匹配了。
1.i (ignore) 可以忽略大小写。
2.g (global) 全局匹配。
1.
2. var reg = /abc/;
3. var str = ‘abcabcabc’;
4. console.log(str.match(reg)); // [“abc”, index: 0, input: “abcabcabc”]
不写g的时候会返回一个类数组,写上g会返回一个数组,里面有所有的3个abc。
1.
2. var reg = /abc/g;
3. var str = ‘abcabcabc’;
4. console.log(str.match(reg)); // [“abc”, “abc”, “abc”]
3.m (multiline)多行匹配
1.
2. var reg = /^e/igm;
3. var str = “abc\nebcd”;
4. console.log(str.match(reg));
这个reg的作用是匹配以e开头的字符串,如果不加m,这个str是无法匹配的,因为\n也算一个字符,它后面的e不算是开头的字符,但是加上m之后,\n就会被正则表达式看成是正常的换行符,因此后面的e会被看做是下一行的开头的字符,因此就可以匹配出来了。
表达式
1.[abc] 查找方括号之间的任何字符。
匹配的是一位字符,不过是括号里面的任何一位都可以。
1.
2. var reg = /[abcd]/g;
3. var str = ‘code’;
4. console.log(str.match(reg)); // [“c”, “d”]
现在反悔的一个数组,把str中的所有a或者b或者c都返回出来了。
我们还可以写一个范围,比如[a-zA-Z0-9],这样就代表所有的英文字母和数字。
1.
2. var reg = /[a-zA-Z0-9]/g;
3. var str = ‘code1024’;
4. console.log(str.match(reg)); // [“c”, “o”, “d”, “e”, “1”, “0”, “2”, “4”]
这样匹配出来的就是一个code1024
2.[^abc] 查找任何不属于方括号里面的字符
注意这里的“^”是写在方括号里面的,和前面的代表开头的“^”不是一个意思。当这个符号出现在方括号里面的时候,就代表非的意思,除了方括号里面写的,其他的字符都符合。
1.
2. var reg = /[^a-zA-Z]/g;
3. var str = ‘code1024’;
4. console.log(str.match(reg)); // [“1”, “0”, “2”, “4”]
这个表达式的意思就是除了字母之外的其他字符都符合要求。
3.()
括号的作用是提高优先级和产生子表达式的作用。
4.|
或表达式,和[]差不多,可以配合()来使用。
1.
2. var reg = /a|b/g;
这个正则表达式代表ab或者cb都可以。
1.
2. var reg = /(a|c)b)/g;
1.
2. var reg =/(blue|red)abc/;
如果不加括号的话,就是匹配blue或者redabc,现在加上括号了就是匹配blueabc或者redabc。
元字符
和表达式差不多,元字符是代表区间的。
1.“.”
这个符号可以匹配除了换行符(\n)和行结束符(\r),除了这两个字符之外其他的字符都可以匹配出来。
2.\w
这个元字符代表单词字符的意思,即A-Za-z0-9_
注意这个是可以匹配下划线的。
3.\W
除了\w的单词字符之外的其他字符。
4.\d
代表数字字符,即0-9
5\D
代表除了数字字符之外的其他字符。
6.\s
查找空白字符。
空白字符都包括:空格符、制表符(\t)、回车符(\r),换行符(\n),垂直换行符(\v)、换页符(\f)。
因此\s = [\n\t\r\v\f];
7.\S
查找非空白字符,即除了\s包括的空白字符之外的其他字符。
我们如果要匹配任意字符的话,就可以搭配起来使用了:
[\s\S]、[\d\D]、[\w\W]等都可以
8.\b
匹配单词边界。
1.
2. var str = ‘accb bdaccd efg’;
3. var reg = /\bacc/;
4. console.log(str.match(reg)); // [“acc”]
这样匹配的就是第一个acc,后面的acc前面不是单词边界,因此不符合匹配规则。
9.\B
非单词边界
1.
2. var str = ‘accb bdaccd efg’;
3. var reg = /\Bacc/;
4. console.log(str.match(reg)); // [“acc”]
匹配的就是中间的acc。
注意,一个汉字就是一个单词,每一个汉字的两边都有默认的单词边界。
1.
2. var str = ‘维生素c’;
3. var reg = /\bc/;
4. console.log(str.match(reg)); // [“c”, index: 3, input: “维生素c”]
量词
以下的n代表一个变量,可以是表达式或者元字符。
1.n+
匹配至少一个变量n
1.
2. var str = ‘bcdaaaaagbaaasaaka’;
3. var reg = /a+/g;
4. console.log(str.match(reg)); // [“aaaaa”, “aaa”, “aa”, “a”]
可以把全部的a当做一位来匹配出来。
2.n*
匹配至少零个变量n
1.
2. var reg = /a*c/g;
3. var str = ‘abc’;
4. console.log(str.match(reg)); // [“c”]
这种情况下只有前面是a*0才有可能匹配成功。
1.
2. var reg = /\w*/g;
3. var str = ‘aabbbccc’;
4. console.log(str.match(reg)); // [“aabbbccc”, “”]
最后有一个空串,因为前面的单词被\w匹配出来,最后还有一个空字符可以被\w0匹配出来。
两个字符之间都有一个空字符, ab-> [‘a’, ”, ‘b’];
3.n?
匹配0-1个变量n
1.
2. var reg=/(aa|b)?/g;
3. var str = ‘aaaaacb’;
4. console.log(str.match(reg)); // [“aa”, “aa”, “”, “”, “b”, “”]
中间的空串是因为匹配了空串,?取0的情况。
4.n{x}
可以规定匹配x个变量n
1.
2. var reg = /a{4}/;
3. var str = ‘aaaaa’;
4. console.log(str.match(reg)); // [“aaaa”, index: 0, input: “aaaaa”]
并且大括号可以写一个区间,中间用逗号链接。
1.
2. var reg = /a{1,4}/g;
3. var str = ‘aaaaa’;
4. console.log(str.match(reg)); // [“aaaa”, “a”]
或者第二个范围不写,这样就代表到无穷的范围。
1.
2. var reg = /a{1,}/g;
3. var str = ‘aaaaa’;
4. console.log(str.match(reg)); // [“aaaaa”]
这里默认的是贪婪匹配,即尽可能匹配多个字符。
1.
2. var reg = /a{1,4}/g;
3. var str = ‘aaaaaa’;
4. console.log(str.match(reg)); // [“aaaa”, “aa”]
当我们在后面加一个”?”之后,就会变成最小匹配,尽可能匹配少的字符。
1.
2. var reg = /a{1,4}?/g;
3. var str = ‘aaaaaa’;
4. console.log(str.match(reg)); // [“a”, “a”, “a”, “a”, “a”, “a”]
当然,不只是{}后面可以加”?”,其他的比如*?、+?等等后面都可以加问号。
5.n$
匹配以n结尾的字符
1.
2. var reg = /ab$/;
3. var str = ‘abab’;
4. console.log(str.match(reg)); // [“ab”, index: 2, input: “abab”]
只能找到最后一组ab
6.^n
匹配以n开头的字符,注意不是[]里面的^。
1.
2. var reg = /^acb/g;
3. var str = ‘acbacb’;
4. console.log(str.match(reg)); // [“acb”]
只能匹配出来第一个acb。
1.
2. var reg = /^ab$/g;;
3. var str = ‘abcabc’;
4. console.log(str.match(reg)); // null
这种写法就要求从a开头,挨着的b是结尾的。”abab“现在就匹配不出来了。
1.
2. var reg = /^abc$/g;;
这种写法可以匹配固定字符串abc。
小题目:
写一个正则表达式,检验字符串首尾是否有数字。
1.
2. var reg = /^\d|\d$/gi;
3. console.log(reg.test(‘12asdfv’)); // true
7.n(?=xxx)
正向预查(正向断言)
1.
2. var reg = /x(?=abc)/g;
3. var str = ‘xabcxbcdaabc’;
4. console.log(str.match(reg)); // x
后面是abc的那个n,匹配的是n,后面有abc是一种条件。
如果n是一个空,那么就查找后面是abc的a前面那个空串了。
1.
2. var reg = /(?=abc)/g;
3. var str = ‘xabcxbcdaabc’;
4. console.log(str.match(reg)); // [“”, “”]
8.n(?!xxx)
非正向预查
匹配后面不是abc的n。
• 我们如果要匹配*、?等这些字符的话,就需要在前面加上一个转义字符“/”了。
RegExp对象
属性
1.global multiline ignoreCase
这三个属性可以检测是否有gim修饰。
2.source
代表正则表达式本身,即两个斜线中间的部分。
1.
2. var reg = /abc\w\d/gim;
3. console.log(reg.source); // abc\w\d
方法
1.exec
这个方法可以检测字符串中指定的值,返回知道的值并确定其位置。
1.
2. var reg = /abc/;
3. var str = “bcabcdabcda”;
4. console.log(reg.exec(str)); // [“abc”, index: 2, input: “bcabcdabcda”]
返回的是一个类数组,其中的index是匹配出的字符开始的位置。
不论执行多少次结果都一样。
jQuery源码里面就用了很多exec方法。
我们前面提到()括号除了优先级之外,还可以产生子表达式。
1.
2. var reg = /(a)(b)(c)/;
3. var str = “bcabcdabcda”;
4. console.log(reg.exec(str)); // [“abc”, “a”, “b”, “c”, index: 2, input: “bcabcdabcda”]
返回的类数组会把三个子表达式匹配的内容也写出来。
第一个子表达式的a是第一个abc里面的a,子表达式b是abc里面的b,子表达式c是abc里面的c。
当我们不想让括号匹配出来字符作为子表达式,只充当优先级的作用的时候,那么在()的最前面加上“?:”就可以取消子表达式的作用了。
1.
2. var reg = /(?:a)(?:b)(c)/;
3. var str = “bcabcdabcda”;
4. console.log(reg.exec(str)); // [“abc”, “c”, index: 2, input: “bcabcdabcda”]
这里的”?:”叫做不记录子表达式。
而有了子表达式,我们也有相应的可以选择出子表达式的表达式。
反向引用:
匹配形如1221形式的字符串,比如abba,deed等。我们可以通过子表达式和反向引用就可以实现。
1.
2. var reg = /(\w)(\w)\2\1/ ;
3. var str = “abba”;
4. console.log(reg.exec(str)); // [“abba”, “a”, “b”, index: 0, input: “abba”]
\1代表和第一个子表达式匹配到的相同的内容,第一个\w匹配到什么这里的\1就是什么,\2同理。
以上是我们的正则表达式没有写g全局时候的情况,当我们写上g之后情况又会变得不一样了。
1.
2. var reg = /abc/g;
3. var str = “bcabcdabcda”;
4. console.log(reg.exec(str)); // [“abc”, index: 2, input: “bcabcdabcda”]
5. console.log(reg.exec(str)); // [“abc”, index: 6, input: “bcabcdabcda”]
执行第一次的结果和没有全局时候是一样的,但是从第二次开始就不同了。
第二次index变成了6,匹配的是第二组abc。
所以加上g之后,后面的匹配开始的位置是从上一次匹配结束的位置开始,而不是从头开始。
如果走到最后也没有符合的字符串的话,就会返回null。但是下一再执行会回到开头开始匹配。
这一切不同之处都是因为正则表达式还有一个属性叫做lastIndex,这个属性基本只有全局的时候才有作用。他会记录表达式上一次匹配完了之后的位置,然后让下一次匹配从lastIndex的位置开始。
如果我们中途改变了lastIndex 的数值,那么我们就可以改变下一次匹配开始的位置了。
1.
2. var reg = /abc/g;
3. var str = “bcabcdabcda”;
4. reg.lastIndex = 4;
5. console.log(reg.exec(str)); // [“abc”, index: 6, input: “bcabcdabcda”]
现在第一次执行结果匹配的就是第二个abc。
String上的一些方法
1.search
检索与正则表达式相匹配的位置,匹配成功即结束,与g无关,匹配失败则会返回-1。
2.match
找到一个或多个正则表达式的匹配,当非全局匹配时和exec显示的一样,是一个类数组,但是没有lastIndex,全局匹配时会返回一个数组。
3.split
split是以什么为分隔符把字符串分割成一个数组,这里的分隔符可以写一个正则表达式。
1.
2. var reg = /[-\d]/g;
3. var str = ‘a-c-d-a0f-e’;
4. console.log(str.split(reg)); // [“a”, “c”, “d”, “a”, “f”, “e”]
4.replace
替换与正则表达式匹配的字串。
这个方法非常非常重要,配合正则表达式会变得很灵活。
str.replace()有两个参数,第一个是目标字符串,可以是一个正则表达式,也可以是一个字符串,第二个参数是替换成的字符串。
1.
2. var str = ‘abcdbcdbcd’;
3. var reg = /ab/g;
4. console.log(str.replace(‘bc’, ‘aa’)); // aaadbcdbcd
只改第一个ab,后面的ab不改。
变成aaadbcdbcd。
如果想要全部替换就要写正则表达式。
1.
2. var str = ‘abcdbcdbcd’;
3. var reg = /(\w)(\w)/g;
4. console.log(str.replace(reg, ‘aa’)); // aaaaaaaaaa
现在有一个字符串“ab”,如果我们想要通过正则表达式来调换两个字母的位置,也需要用这个方法。
在第二个参数的位置,字符串里面可以写$、$1、$2…等等,其中$代表匹配出来的字符串,$1代表子表达式1,$2代表子表达式2.。
这样我们通过这种参数就可以实现简单的交换字母了。
1.
2. var str = ‘ab’;
3. var reg = /(\w)(\w)/g;
4. console.log(str.replace(reg, ‘$2$1’)); // ba
当然这只是第一种用法,还有第二种用法,在第二个参数中可以传一个函数,系统会自动调用这个函数,然后替换成这个函数返回的字符串。
var str = ‘ab’;
var reg = /(\w)(\w)/g;
console.log(str.replace(reg, function () {
return ‘abc’
})); // abc
整体被替换成了abc。
函数可以写形参,从前到后分别代表匹配出来的字符串、第一个子表达式、第二个子表达式等等。
1.
2. var str = ‘ab’;
3. var reg = /(\w)(\w)/g;
4. console.log(str.replace(reg, function ($, $1, $2) {
5. return $2 + $1;
6. })); // ba
这个样子同样可以实现交换字母的功能。
正则表达式的大部分知识点就这么多哟~
下面我们来做几个题目练习一下正则表达式的使用吧!
1.将形如aaaabbbb字符串调换成bbbbaaaa形式。
1.
2. var str = ‘aaaabbbb’;
3. var reg = /(\w{4})(\w{4})/g;
4. str.replace(reg, ‘$2$1’);
2.将‘my-fist-name’这样的用‘-’连接字符串变成小驼峰式的写法。
1.
2. var str = ‘my-first-name’;
3. var reg = /-(\w)/g;
4. str.replace(reg, function ($, $1) {
5. return $1.toUpperCase();
6. })
3.将一串连续的数字,变成如下形式:
100000000 —> 100,000,000
1.
2. var str = ‘100000000’;
3. var reg = /(?=((\B)\d{3})+$)/g;
4. console.log(str.replace(reg, ‘,’));