1.概述
正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。比如,正则表达式给出一个 Email 地址的模式,然后用它来确定一个字符串是否为 Email 地址。JavaScript 的正则表达式体系是参照 Perl 5 建立的。
新建正则表达式有两种方法。一种是使用字面量,以斜杠表示开始和结束。
var regex = /xyz/;
另一种是使用RegExp
构造函数。
var regex = new RegExp('xyz');
上面两种写法是等价的,都新建了一个内容为xyz
的正则表达式对象。它们的主要区别是,第一种方法在引擎编译代码时,就会新建正则表达式,第二种方法在运行时新建正则表达式,所以前者的效率较高。而且,前者比较便利和直观,所以实际应用中,基本上都采用字面量定义正则表达式。
RegExp
构造函数还可以接受第二个参数,表示修饰符(详细解释见下文)。
var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
上面代码中,正则表达式/xyz/
有一个修饰符i
。
2.实例属性
正则对象的实例属性分成两类。
一类是修饰符相关,返回一个布尔值,表示对应的修饰符是否设置。
- RegExp.prototype.ignoreCase:返回一个布尔值,表示是否设置了
i
修饰符。 - RegExp.prototype.global:返回一个布尔值,表示是否设置了
g
修饰符。 - RegExp.prototype.multiline:返回一个布尔值,表示是否设置了
m
修饰符。
上面三个属性都是只读的。
var r = /abc/igm;
r.ignoreCase // true
r.global // true
r.multiline // true
另一类是与修饰符无关的属性,主要是下面两个。
RegExp.prototype.lastIndex
:返回一个数值,表示下一次开始搜索的位置。该属性可读写,但是只在进行连续搜索时有意义,详细介绍请看后文。
RegExp.prototype.source
:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
var r = /abc/igm;
r.lastIndex // 0
r.source // "abc"
3.实例方法
3.1 RegExp.prototype.test()
正则实例对象的test
方法返回一个布尔值,表示当前模式是否能匹配参数字符串。
/cat/.test('cats and dogs') // true
上面代码验证参数字符串之中是否包含cat
,结果返回true
。
如果正则表达式带有g
修饰符,则每一次test
方法都从上一次结束的位置开始向后匹配。
var r = /x/g;
var s = '_x_x';
r.lastIndex // 0
r.test(s) // true
r.lastIndex // 2
r.test(s) // true
r.lastIndex // 4
r.test(s) // false
上面代码的正则表达式使用了g
修饰符,表示是全局搜索,会有多个结果。接着,三次使用test
方法,每一次开始搜索的位置都是上一次匹配的后一个位置。
带有g
修饰符时,可以通过正则对象的lastIndex
属性指定开始搜索的位置。
var r = /x/g;
var s = '_x_x';
r.lastIndex = 4;
r.test(s) // false
上面代码指定从字符串的第五个位置开始搜索,这个位置是没有字符的,所以返回false
。
lastIndex
属性只对同一个正则表达式有效,所以下面这样写是错误的。
var count = 0;
while (/a/g.test('babaa')) count++;
上面代码会导致无限循环,因为while
循环的每次匹配条件都是一个新的正则表达式,导致lastIndex
属性总是等于0。
如果正则模式是一个空字符串,则匹配所有字符串。
new RegExp('').test('abc')
// true
3.2 RegExp.prototype.exec()
正则实例对象的exec
方法,用来返回匹配结果。如果发现匹配,就返回一个数组,成员是匹配成功的子字符串,否则返回null
。
var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
r1.exec(s) // ["x"]
r2.exec(s) // null
上面代码中,正则对象r1
匹配成功,返回一个数组,成员是匹配结果;正则对象r2
匹配失败,返回null
。
如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的length
属性等于组匹配的数量再加1。
var s = '_x_x';
var r = /_(x)/;
r.exec(s) // ["_x", "x"]
上面代码的exec
方法,返回一个数组。第一个成员是整个匹配的结果,第二个成员是圆括号匹配的结果。
exec
方法的返回数组还包含以下两个属性:
-
input
:整个原字符串。 -
index
:整个模式匹配成功的开始位置(从0开始计数)。
var r = /a(b+)a/;
var arr = r.exec('_abbba_aba_');
arr // ["abbba", "bbb"]
arr.index // 1
arr.input // "_abbba_aba_"
上面代码中的index
属性等于1,是因为从原字符串的第二个位置开始匹配成功。
如果正则表达式加上g
修饰符,则可以使用多次exec
方法,下一次搜索的位置从上一次匹配成功结束的位置开始。
var reg = /a/g;
var str = 'abc_abc_abc'
var r1 = reg.exec(str);
r1 // ["a"]
r1.index // 0
reg.lastIndex // 1
var r2 = reg.exec(str);
r2 // ["a"]
r2.index // 4
reg.lastIndex // 5
var r3 = reg.exec(str);
r3 // ["a"]
r3.index // 8
reg.lastIndex // 9
var r4 = reg.exec(str);
r4 // null
reg.lastIndex // 0
上面代码连续用了四次exec
方法,前三次都是从上一次匹配结束的位置向后匹配。当第三次匹配结束以后,整个字符串已经到达尾部,匹配结果返回null
,正则实例对象的lastIndex
属性也重置为0
,意味着第四次匹配将从头开始。
利用g
修饰符允许多次匹配的特点,可以用一个循环完成全部匹配。
var reg = /a/g;
var str = 'abc_abc_abc'
while(true) {
var match = reg.exec(str);
if (!match) break;
console.log('#' + match.index + ':' + match[0]);
}
// #0:a
// #4:a
// #8:a
上面代码中,只要exec
方法不返回null
,就会一直循环下去,每次输出匹配的位置和匹配的文本。
正则实例对象的lastIndex
属性不仅可读,还可写。设置了g
修饰符的时候,只要手动设置了lastIndex
的值,就会从指定位置开始匹配。
4.3 String.prototype.replace()
字符串对象的replace
方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。
str.replace(search, replacement)
正则表达式如果不加g
修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值。
'aaa'.replace('a', 'b') // "baa"
'aaa'.replace(/a/, 'b') // "baa"
'aaa'.replace(/a/g, 'b') // "bbb"
上面代码中,最后一个正则表达式使用了g
修饰符,导致所有的b
都被替换掉了。
replace
方法的一个应用,就是消除字符串首尾两端的空格。
var str = ' #id div.class ';
str.replace(/^\s+|\s+$/g, '')
// "#id div.class"
replace
方法的第二个参数可以使用美元符号$
,用来指代所替换的内容。
- $&:匹配的子字符串。
- $`:匹配结果前面的文本。
- $’:匹配结果后面的文本。
- $n:匹配成功的第
n
组内容,n
是从1开始的自然数。 - $$:指代美元符号
$
。
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// "world hello"
'abc'.replace('b', '[$`-$&-$\']')
// "a[a-b-c]c"
上面代码中,第一个例子是将匹配的组互换位置,第二个例子是改写匹配的值。
replace
方法的第二个参数还可以是一个函数,将每一个匹配内容替换为函数返回值。
'3 and 5'.replace(/[0-9]+/g, function (match) {
return 2 * match;
})
// "6 and 10"
var a = 'The quick brown fox jumped over the lazy dog.';
var pattern = /quick|brown|lazy/ig;
a.replace(pattern, function replacer(match) {
return match.toUpperCase();
});
// The QUICK BROWN fox jumped over the LAZY dog.
作为replace
方法第二个参数的替换函数,可以接受多个参数。其中,第一个参数是捕捉到的内容,第二个参数是捕捉到的组匹配(有多少个组匹配,就有多少个对应的参数)。此外,最后还可以添加两个参数,倒数第二个参数是捕捉到的内容在整个字符串中的位置(比如从第五个位置开始),最后一个参数是原字符串。下面是一个网页模板替换的例子。
var prices = {
'p1': '$1.99',
'p2': '$9.99',
'p3': '$5.00'
};
var template = ''
+ ''
+ '';
template.replace(
/()(<\/span>)/g,
function(match, $1, $2, $3, $4){
return $1 + $2 + $3 + prices[$2] + $4;
}
);
// "$1.99$9.99$5.00"
上面代码的捕捉模式中,有四个括号,所以会产生四个组匹配,在匹配函数中用$1
到$4
表示。匹配函数的作用是将价格插入模板中。
RegExp 是javascript中的一个内置对象。为正则表达式。
RegExp.$1是RegExp的一个属性,指的是与正则表达式匹配的第一个 子匹配(以括号为标志)字符串,以此类推,RegExp.$2,RegExp.$3,..RegExp.$99总共可以有99个匹配例子:
var r= /^(\d{4})-(\d{1,2})-(\d{1,2})$/; //正则表达式 匹配出生日期(简单匹配)
r.exec('1985-10-15');
s1=RegExp.$1;
s2=RegExp.$2;
s3=RegExp.$3;
alert(s1+" "+s2+" "+s3)//结果为1985 10 15
Notification.permission
Notification 的只读属性 permission 用来表明用户是否允许当前域显示Web Notification.
Syntax
var permission = Notification.permission;
Value
permission 的类型为 DOMString
. 该属性的可能值为:
-
granted
: 用户已经明确的授予了显示通知的权限。. -
denied
: 用户已经明确的拒绝了显示通知的权限。 -
default
: 用户还未被询问是否授权; 这种情况下权限将视为denied
.
Examples
下面的代码片段详细的说明了,当你首次检查浏览器是否支持Notification,然后检查当前域是否被授予了发送Notification的权限,并且在发送一个通知前进行请求的用法.
function notifyMe() {
// Let's check if the browser supports notifications
if (!("Notification" in window)) {
console.log("This browser does not support desktop notification");
}
// Let's check whether notification permissions have alredy been granted
else if (Notification.permission === "granted") {
// If it's okay let's create a notification
var notification = new Notification("Hi there!");
}
// Otherwise, we need to ask the user for permission
else if (Notification.permission !== 'denied' || Notification.permission === "default") {
Notification.requestPermission(function (permission) {
// If the user accepts, let's create a notification
if (permission === "granted") {
var notification = new Notification("Hi there!");
}
});
}
// At last, if the user has denied notifications, and you
// want to be respectful there is no need to bother them any more.
}
notification
Notifications API 的通知接口用于向用户配置和显示桌面通知。
构造方法
let notification = new Notification(title, options)
参数
-
title
一定会被显示的通知标题
-
options
可选一个被允许用来设置通知的对象。它包含以下属性:
dir
: 文字的方向;它的值可以是auto(自动)
,ltr(从左到右)
, orrtl
(从右到左)lang
: 指定通知中所使用的语言。body
: 通知中额外显示的字符串。tag
: 赋予通知一个ID,以便在必要的时候对通知进行刷新、替换或移除。icon
: 一个图片的URL,将被用于显示通知的图标。
属性
静态属性
这些属性仅在 Notification
对象上有效。
-
Notification.permission
只读一个用于表明当前通知显示授权状态的字符串。可能的值包括:
denied
(用户拒绝了通知的显示),granted
(用户允许了通知的显示), 或default
(因为不知道用户的选择,所以浏览器的行为与 denied 时相同).
实例属性
这些属性仅在 Notification
的实例中有效。
-
Notification.title
只读 (moz only)在构造方法中指定的 title 参数。
-
Notification.dir
只读通知的文本显示方向。在构造方法的 options 中指定。
-
Notification.lang
只读通知的语言。在构造方法的 options 中指定。
-
Notification.body
只读通知的文本内容。在构造方法的 options 中指定。
-
Notification.tag
只读通知的 ID。在构造方法的 options 中指定。
-
Notification.icon
只读通知的图标图片的 URL 地址。在构造方法的 options 中指定。
事件处理
-
Notification.onclick
处理
click
事件的处理。每当用户点击通知时被触发。 -
Notification.onshow
处理
show
事件的处理。当通知显示的时候被触发。 -
Notification.onerror
处理
error
事件的处理。每当通知遇到错误时被触发。 -
Notification.onclose
处理
close
事件的处理。当用户关闭通知时被触发。
方法
静态方法
这些方法仅在 Notification
对象中有效。
-
Notification.requestPermission()
用于当前页面向用户申请显示通知的权限。这个方法只能被用户行为调用(比如:onclick 事件),并且不能被其他的方式调用。
实例方法
实例方法
这些方法仅在 Notification
实例或其 prototype
中有效。
-
Notification.close()
用于关闭通知。
Notification
对象继承自 EventTarget
接口。
-
EventTarget.addEventListener()
Registers an event handler of a specific event type on the
EventTarget
. -
EventTarget.removeEventListener()
Removes an event listener from the
EventTarget
. -
EventTarget.dispatchEvent()
Dispatches an event to this
EventTarget
.
Example
假定有如下 HTML:
接下来发送一条通知:
function notifyMe() {
// 先检查浏览器是否支持
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
}
// 检查用户是否同意接受通知
else if (Notification.permission === "granted") {
// If it's okay let's create a notification
var notification = new Notification("Hi there!");
}
// 否则我们需要向用户获取权限
else if (Notification.permission !== 'denied') {
Notification.requestPermission(function (permission) {
// 如果用户同意,就可以向他们发送通知
if (permission === "granted") {
var notification = new Notification("Hi there!");
}
});
}
// 最后,如果执行到这里,说明用户已经拒绝对相关通知进行授权
// 出于尊重,我们不应该再打扰他们了
}
权限
当你要在开放 web 应用中使用通知时,请确保将 desktop-notification
权限添加到你的 manifest 文件中。通知可以被用于任何权限级别,hosted 或更高。
"permissions": {
"desktop-notification":{}
}