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); // “”
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
转义字符配合特殊的字母有特殊的意义:
\n 代表字符串和换行
\r 代表字符串的回车
\t 代表制表符tab
等等
多行字符串
1.真正的多行字符串,在每一行最后加一个\n就可以了。
2.为了让结构看起来清晰,我们在编辑器中人为的换行,但是本身并不是多行字符串,这个时候只需要在每一行末尾加一个“\”就可以了。
1. 2. var str = ‘\ 3. <div class=”demo”>\ 4. <span></span>\ 5. <p></p>\ 6. </div>\ 7. ‘
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
了解了转义字符之后,下面我们正式进入正则表达式部分。
正则表达式的作用
正则表达式是进行字符串匹配检测的,当我们为了匹配特殊字符或有特殊匹配原则的字符的时候,正则表达式是最佳的选择。
正则表达式(RegExp)有两种创建方式:
1.直接量
1. 2. var reg = /abc/;
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
2.构造函数
1. 2. var reg = new RegExp(‘abc’);
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
要匹配的字符串放在第一个参数,或者将一个现成的正则表达式放进第一个参数。
1. 2. var reg = /abc/; 3. var reg2 = new RegExp(reg);
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
修饰符
一个正则表达式有三个描述的属性g、i、m,表示三种特定的修饰功能。
1. 2. var reg = /abc/gim;
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
在直接量中直接在后面加上gim就可以了,但是在构造函数中,我们要把修饰符放在第二个参数上。
1. 2. var reg = new RegExp(‘abc’, ‘gim’);
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这两种写出来的效果是一模一样的,但是由于构造函数书写起来太麻烦而且还需要转义字符,个人推荐用直接量来构造正则表达式。
正则表达式上面有一个方法test(),可以测试一个字符串符不符合这个匹配规则。
1. 2. var reg = /abc/g; 3. console.log(reg.test(‘abcabc’)); // true
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这样就实现了一个最基本的匹配了。
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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
不写g的时候会返回一个类数组,写上g会返回一个数组,里面有所有的3个abc。
1. 2. var reg = /abc/g; 3. var str = ‘abcabcabc’; 4. console.log(str.match(reg)); // [“abc”, “abc”, “abc”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
3.m (multiline)多行匹配
1. 2. var reg = /^e/igm; 3. var str = “abc\nebcd”; 4. console.log(str.match(reg));
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这个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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
现在反悔的一个数组,把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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这样匹配出来的就是一个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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这个表达式的意思就是除了字母之外的其他字符都符合要求。
3.()
括号的作用是提高优先级和产生子表达式的作用。
4.|
或表达式,和[]差不多,可以配合()来使用。
1. 2. var reg = /a|b/g;
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这个正则表达式代表ab或者cb都可以。
1. 2. var reg = /(a|c)b)/g;
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
1. 2. var reg =/(blue|red)abc/;
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
如果不加括号的话,就是匹配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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这样匹配的就是第一个acc,后面的acc前面不是单词边界,因此不符合匹配规则。
9.\B
非单词边界
1. 2. var str = ‘accb bdaccd efg’; 3. var reg = /\Bacc/; 4. console.log(str.match(reg)); // [“acc”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
匹配的就是中间的acc。
注意,一个汉字就是一个单词,每一个汉字的两边都有默认的单词边界。
1. 2. var str = ‘维生素c’; 3. var reg = /\bc/; 4. console.log(str.match(reg)); // [“c”, index: 3, input: “维生素c”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
量词
以下的n代表一个变量,可以是表达式或者元字符。
1.n+
匹配至少一个变量n
1. 2. var str = ‘bcdaaaaagbaaasaaka’; 3. var reg = /a+/g; 4. console.log(str.match(reg)); // [“aaaaa”, “aaa”, “aa”, “a”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
可以把全部的a当做一位来匹配出来。
2.n*
匹配至少零个变量n
1. 2. var reg = /a*c/g; 3. var str = ‘abc’; 4. console.log(str.match(reg)); // [“c”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这种情况下只有前面是a*0才有可能匹配成功。
1. 2. var reg = /\w*/g; 3. var str = ‘aabbbccc’; 4. console.log(str.match(reg)); // [“aabbbccc”, “”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
最后有一个空串,因为前面的单词被\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”, “”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
中间的空串是因为匹配了空串,?取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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
并且大括号可以写一个区间,中间用逗号链接。
1. 2. var reg = /a{1,4}/g; 3. var str = ‘aaaaa’; 4. console.log(str.match(reg)); // [“aaaa”, “a”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
或者第二个范围不写,这样就代表到无穷的范围。
1. 2. var reg = /a{1,}/g; 3. var str = ‘aaaaa’; 4. console.log(str.match(reg)); // [“aaaaa”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这里默认的是贪婪匹配,即尽可能匹配多个字符。
1. 2. var reg = /a{1,4}/g; 3. var str = ‘aaaaaa’; 4. console.log(str.match(reg)); // [“aaaa”, “aa”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
当我们在后面加一个”?”之后,就会变成最小匹配,尽可能匹配少的字符。
1. 2. var reg = /a{1,4}?/g; 3. var str = ‘aaaaaa’; 4. console.log(str.match(reg)); // [“a”, “a”, “a”, “a”, “a”, “a”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
当然,不只是{}后面可以加”?”,其他的比如*?、+?等等后面都可以加问号。
5.n$
匹配以n结尾的字符
1. 2. var reg = /ab$/; 3. var str = ‘abab’; 4. console.log(str.match(reg)); // [“ab”, index: 2, input: “abab”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
只能找到最后一组ab
6.^n
匹配以n开头的字符,注意不是[]里面的^。
1. 2. var reg = /^acb/g; 3. var str = ‘acbacb’; 4. console.log(str.match(reg)); // [“acb”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
只能匹配出来第一个acb。
1. 2. var reg = /^ab$/g;; 3. var str = ‘abcabc’; 4. console.log(str.match(reg)); // null
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这种写法就要求从a开头,挨着的b是结尾的。”abab“现在就匹配不出来了。
1. 2. var reg = /^abc$/g;;
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这种写法可以匹配固定字符串abc。
小题目:
写一个正则表达式,检验字符串首尾是否有数字。
1. 2. var reg = /^\d|\d$/gi; 3. console.log(reg.test(‘12asdfv’)); // true
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
7.n(?=xxx)
正向预查(正向断言)
1. 2. var reg = /x(?=abc)/g; 3. var str = ‘xabcxbcdaabc’; 4. console.log(str.match(reg)); // x
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
后面是abc的那个n,匹配的是n,后面有abc是一种条件。
如果n是一个空,那么就查找后面是abc的a前面那个空串了。
1. 2. var reg = /(?=abc)/g; 3. var str = ‘xabcxbcdaabc’; 4. console.log(str.match(reg)); // [“”, “”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
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
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
方法
1.exec
这个方法可以检测字符串中指定的值,返回知道的值并确定其位置。
1. 2. var reg = /abc/; 3. var str = “bcabcdabcda”; 4. console.log(reg.exec(str)); // [“abc”, index: 2, input: “bcabcdabcda”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
返回的是一个类数组,其中的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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
返回的类数组会把三个子表达式匹配的内容也写出来。
第一个子表达式的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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这里的”?:”叫做不记录子表达式。
而有了子表达式,我们也有相应的可以选择出子表达式的表达式。
反向引用:
匹配形如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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
\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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
执行第一次的结果和没有全局时候是一样的,但是从第二次开始就不同了。
第二次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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
现在第一次执行结果匹配的就是第二个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”]
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
4.replace
替换与正则表达式匹配的字串。
这个方法非常非常重要,配合正则表达式会变得很灵活。
str.replace()有两个参数,第一个是目标字符串,可以是一个正则表达式,也可以是一个字符串,第二个参数是替换成的字符串。
1. 2. var str = ‘abcdbcdbcd’; 3. var reg = /ab/g; 4. console.log(str.replace(‘bc’, ‘aa’)); // aaadbcdbcd
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
只改第一个ab,后面的ab不改。
变成aaadbcdbcd。
如果想要全部替换就要写正则表达式。
1. 2. var str = ‘abcdbcdbcd’; 3. var reg = /(\w)(\w)/g; 4. console.log(str.replace(reg, ‘aa’)); // aaaaaaaaaa
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
现在有一个字符串“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
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
当然这只是第一种用法,还有第二种用法,在第二个参数中可以传一个函数,系统会自动调用这个函数,然后替换成这个函数返回的字符串。
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
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
这个样子同样可以实现交换字母的功能。
正则表达式的大部分知识点就这么多哟~
下面我们来做几个题目练习一下正则表达式的使用吧!
1.将形如aaaabbbb字符串调换成bbbbaaaa形式。
1. 2. var str = ‘aaaabbbb’; 3. var reg = /(\w{4})(\w{4})/g; 4. str.replace(reg, ‘$2$1’);
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
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. })
JavaScript; “复制代码”); “查看纯文本代码”); “返回代码高亮”)
3.将一串连续的数字,变成如下形式:
100000000 —> 100,000,000
1. 2. var str = ‘100000000’; 3. var reg = /(?=((\B)\d{3})+$)/g; 4. console.log(str.replace(reg, ‘,’));