Object
对象,即那些对象都是Object
的实例。Object
对象的原生方法分红两类:Object
自己的方法与Object
的实例方法。(1)Object对象自己的方法(静态方法)javascript
所谓“自己的方法”就是直接定义在Object
对象的方法。java
Object.print = function (o) { console.log(o) };
复制代码
上面代码中,print
方法就是直接定义在Object
对象上。正则表达式
(2)Object的实例方法编程
所谓实例方法就是定义在Object
原型对象Object.prototype
上的方法。它能够被Object
实例直接使用。数组
Object.prototype.print = function () {
console.log(this);
};
var obj = new Object();
obj.print() // Object
复制代码
Object自己是一个函数,能够看成工具方法使用,将任意值转为对象。这个方法经常使用于保证某个值必定是对象。bash
Object
方法的参数是一个对象,它老是返回该对象,即不用转换。利用这一点,能够写一个判断变量是否为对象的函数。数据结构
function isObject(value) {
return value === Object(value);
}
isObject([]) // true
isObject(true) // false
复制代码
Object.keys()方法的参数是一个对象,返回一个数组。该数组的成员都是该对象自身的全部属性名。(可枚举) Object.getOwnPropertyNames()返回一个数组,包含了该对象自身的全部属性名(不可枚举)app
(1)对象属性模型的相关方法 Object.getOwnPropertyDescriptor():获取某个属性的描述对象。 Object.defineProperty():经过描述对象,定义某个属性。 Object.defineProperties():经过描述对象,定义多个属性。函数
(2)控制对象状态的方法 Object.preventExtensions():防止对象扩展。 Object.isExtensible():判断对象是否可扩展。 Object.seal():禁止对象配置。 Object.isSealed():判断一个对象是否可配置。 Object.freeze():冻结一个对象。 Object.isFrozen():判断一个对象是否被冻结。工具
(3)原型链相关方法 Object.create():该方法能够指定原型对象和属性,返回一个新的对象。 Object.getPrototypeOf():获取对象的Prototype对象。
除了静态方法,还有很多方法定义在Object.prototype
对象。它们称为实例方法,全部Object
的实例对象都继承了这些方法。
Object实例对象的方法,主要有如下六个。
Object.prototype.valueOf():返回当前对象对应的值。 Object.prototype.toString():返回当前对象对应的字符串形式。 Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。 Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,仍是继承自原型对象的属性。 Object.prototype.isPrototypeOf():判断当前对象是否为另外一个对象的原型。 Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。
技巧:只作一个精确的类型判断方法
var type = function (o){
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
复制代码
延伸:判断具体类型的方法
var type = function (o){
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
['Null',
'Undefined',
'Object',
'Array',
'String',
'Number',
'Boolean',
'Function',
'RegExp'
].forEach(function (t) {
type['is' + t] = function (o) {
return type(o) === t.toLowerCase();
};
});
type.isObject({}) // true
type.isNumber(NaN) // true
type.isRegExp(/abc/) // true
复制代码
JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,好比该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每一个属性都有本身对应的属性描述对象,保存该属性的一些元信息。
下面是属性描述对象的一个例子。
{
value: 123,
writable: false,
enumerable: true,
configurable: false,
get: undefined,
set: undefined
}
复制代码
属性描述对象提供6个元属性。
(1)value
value
是该属性的属性值,默认为undefined
。
(2)writable
writable
是一个布尔值,表示属性值(value)是否可改变(便是否可写),默认为true
。
(3)enumerable
enumerable
是一个布尔值,表示该属性是否可遍历,默认为true
。若是设为false
,会使得某些操做(好比for...in
循环、Object.keys()
)跳过该属性。
(4)configurable
configurable
是一个布尔值,表示可配置性,默认为true
。若是设为false
,将阻止某些操做改写该属性,好比没法删除该属性,也不得改变该属性的属性描述对象(value
属性除外)。也就是说,configurable
属性控制了属性描述对象的可写性。
(5)get
get
是一个函数,表示该属性的取值函数(getter),默认为undefined
。
(6)set
set
是一个函数,表示该属性的存值函数(setter),默认为undefined
。
若是一个属性的enumerable
为false
,下面三个操做不会取到该属性。
for..in
循环Object.keys
方法JSON.stringify
方法所以,enumerable
能够用来设置“秘密”属性。
正常写法
var obj = Object.defineProperty({}, 'p', {
get: function () {
return 'getter';
},
set: function (value) {
console.log('setter: ' + value);
}
});
复制代码
特殊写法
JavaScript 还提供了存取器的另外一种写法。
var obj = {
get p() {
return 'getter';
},
set p(value) {
console.log('setter: ' + value);
}
};
复制代码
属性的元对象设置都会拷贝
var extend = function (to, from) {
for (var property in from) {
if (!from.hasOwnProperty(property)) continue;
Object.defineProperty(
to,
property,
Object.getOwnPropertyDescriptor(from, property)
);
}
return to;
}
extend({}, { get a(){ return 1 } })
复制代码
有时须要冻结对象的读写状态,防止对象被改变。JavaScript 提供了三种冻结方法,最弱的一种是Object.preventExtensions
,其次是Object.seal
,最强的是Object.freeze
。
1.Object.preventExtensions
方法可使得一个对象没法再添加新的属性。
Object.isExtensible
方法用于检查一个对象是否使用了Object.preventExtensions
方法。也就是说,检查是否能够为一个对象添加属性。
2.Object.seal
方法使得一个对象既没法添加新属性,也没法删除旧属性。
Object.isSealed
方法用于检查一个对象是否使用了Object.seal
方法。
3.Object.freeze
方法可使得一个对象没法添加新属性、没法删除旧属性、也没法改变属性的值,使得这个对象实际上变成了常量。
Object.isFrozen
方法用于检查一个对象是否使用了Object.freeze
方法。
上面的三个方法锁定对象的可写性有一个漏洞:能够经过改变原型对象,来为对象增长属性。
一种解决方案是,把obj
的原型也冻结住。
另一个局限是,若是属性值是对象,上面这些方法只能冻结属性指向的对象,而不能冻结对象自己的内容。
var obj = {
foo: 1,
bar: ['a', 'b']
};
Object.freeze(obj);
obj.bar.push('c');
obj.bar // ["a", "b", "c"]
复制代码
上面代码中,obj.bar
属性指向一个数组,obj
对象被冻结之后,这个指向没法改变,即没法指向其余值,可是所指向的数组是能够改变的。
Array
是 JavaScript 的原生对象,同时也是一个构造函数,能够用它生成新的数组。
Array
构造函数有一个很大的缺陷,就是不一样的参数,会致使它的行为不一致。
// 无参数时,返回一个空数组
new Array() // []
// 单个正整数参数,表示返回的新数组的长度
new Array(1) // [ empty ]
new Array(2) // [ empty x 2 ]
// 非正整数的数值做为参数,会报错
new Array(3.2) // RangeError: Invalid array length
new Array(-3) // RangeError: Invalid array length
// 单个非数值(好比字符串、布尔值、对象等)做为参数,
// 则该参数是返回的新数组的成员
new Array('abc') // ['abc']
new Array([1]) // [Array[1]]
// 多参数时,全部参数都是返回的新数组的成员
new Array(1, 2) // [1, 2]
new Array('a', 'b', 'c') // ['a', 'b', 'c']
复制代码
因此不建议使用构造函数建立数组,推荐用字面量建立
Array.isArray
方法返回一个布尔值,表示参数是否为数组。它能够弥补typeof
运算符的不足。
valueOf
方法是一个全部对象都拥有的方法,表示对该对象求值。不一样对象的valueOf
方法不尽一致,数组的valueOf
方法返回数组自己。
toString
方法也是对象的通用方法,数组的toString
方法返回数组的字符串形式。
push
方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
pop
方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。
push
和pop
结合使用,就构成了“后进先出”的栈结构(stack)。
shift()
方法用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。push()
和shift()
结合使用,就构成了“先进先出”的队列结构(queue)。
unshift()
方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
join()
方法以指定参数做为分隔符,将全部数组成员链接为一个字符串返回。若是不提供参数,默认用逗号分隔。
concat
方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,而后返回一个新数组,原数组不变。
reverse
方法用于颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组。
slice
方法用于提取目标数组的一部分,返回一个新数组,原数组不变。
它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素自己不包括在内)。若是省略第二个参数,则一直返回到原数组的最后一个成员。
splice
方法用于删除原数组的一部分红员,并能够在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。
splice
的第一个参数是删除的起始位置(从0开始),第二个参数是被删除的元素个数。若是后面还有更多的参数,则表示这些就是要被插入数组的新元素。
sort
方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。
map
方法将数组的全部成员依次传入参数函数,而后把每一次的执行结果组成一个新数组返回。
map
方法还能够接受第二个参数,用来绑定回调函数内部的this
变量(详见《this 变量》一章)。
var arr = ['a', 'b', 'c'];
[1, 2].map(function (e) {
return this[e];
}, arr)
// ['b', 'c']
复制代码
上面代码经过map
方法的第二个参数,将回调函数内部的this
对象,指向arr
数组。
若是数组有空位,map
方法的回调函数在这个位置不会执行,会跳过数组的空位。
var f = function (n) { return 'a' };
[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]
复制代码
filter
方法用于过滤数组成员,知足条件的成员组成一个新数组返回。
some
方法是只要一个成员的返回值是true
,则整个some
方法的返回值就是true
,不然返回false
。
some
方法是只要一个成员的返回值是true
,则整个some
方法的返回值就是true
,不然返回false
。
reduce
方法和reduceRight
方法依次处理数组的每一个成员,最终累计为一个值。它们的差异是,reduce
是从左到右处理(从第一个成员到最后一个成员),reduceRight
则是从右到左(从最后一个成员到第一个成员),其余彻底同样。
reduce
方法和reduceRight
方法的第一个参数都是一个函数。该函数接受如下四个参数。
indexOf
方法返回给定元素在数组中第一次出现的位置,若是没有出现则返回-1
lastIndexOf
方法返回给定元素在数组中最后一次出现的位置,若是没有出现则返回-1
。
返回值是数组的能够进行链式使用
对象是 JavaScript 语言最主要的数据类型,三种原始类型的值——数值、字符串、布尔值——在必定条件下,也会自动转为对象,也就是原始类型的“包装对象”(wrapper)。
所谓“包装对象”,指的是与数值、字符串、布尔值分别相对应的Number
、String
、Boolean
三个原生对象。这三个原生对象能够把原始类型的值变成(包装成)对象。
上面代码中,基于原始类型的值,生成了三个对应的包装对象。能够看到,v1
、v2
、v3
都是对象,且与对应的简单类型值不相等。
包装对象的设计目的,首先是使得“对象”这种类型能够覆盖 JavaScript 全部的值,整门语言有一个通用的数据模型,其次是使得原始类型的值也有办法调用本身的方法。
Number
、String
和Boolean
这三个原生对象,若是不做为构造函数调用(即调用时不加new
),而是做为普通函数调用,经常用于将任意类型的值转为数值、字符串和布尔值。
某些场合,原始类型的值会自动看成包装对象调用,即调用包装对象的属性和方法。这时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,并在使用后马上销毁实例。
好比,字符串能够调用length
属性,返回字符串的长度。
'abc'.length // 3
复制代码
上面代码中,abc
是一个字符串,自己不是对象,不能调用length
属性。JavaScript 引擎自动将其转为包装对象,在这个对象上调用length
属性。调用结束后,这个临时对象就会被销毁。这就叫原始类型与实例对象的自动转换。
自动转换生成的包装对象是只读的,没法修改。因此,字符串没法添加新属性。
var s = 'Hello World';
s.x = 123;
s.x // undefined
复制代码
上面代码为字符串s
添加了一个x
属性,结果无效,老是返回undefined
。
另外一方面,调用结束后,包装对象实例会自动销毁。这意味着,下一次调用字符串的属性时,实际是调用一个新生成的对象,而不是上一次调用时生成的那个对象,因此取不到赋值在上一个对象的属性。若是要为字符串添加属性,只有在它的原型对象String.prototype
上定义(参见《面向对象编程》章节)。
除了原生的实例方法,包装对象还能够自定义方法和属性,供原始类型的值直接调用。(标准规范不推荐的)
String.prototype.double = function () {
return this.valueOf() + this.valueOf();
};
'abc'.double()
// abcabc
Number.prototype.double = function () {
return this.valueOf() + this.valueOf();
};
(123).double() // 246
复制代码
上面代码在String
和Number
这两个对象的原型上面,分别自定义了一个方法,从而能够在全部实例对象上调用。注意,最后一张的123
外面必需要加上圆括号,不然后面的点运算符(.
)会被解释成小数点。
Number
对象是数值对应的包装对象
Number.POSITIVE_INFINITY
:正的无限,指向Infinity
。Number.NEGATIVE_INFINITY
:负的无限,指向-Infinity
。Number.NaN
:表示非数值,指向NaN
。Number.MIN_VALUE
:表示最小的正数(即最接近0的正数,在64位浮点数体系中为5e-324
),相应的,最接近0的负数为-Number.MIN_VALUE
。Number.MAX_SAFE_INTEGER
:表示可以精确表示的最大整数,即9007199254740991
。Number.MIN_SAFE_INTEGER
:表示可以精确表示的最小整数,即-9007199254740991
。 Number.prototype.toString()
Number
对象部署了本身的toString
方法,用来将一个数值转为字符串形式。
(10).toString() // "10"
复制代码
Number
对象部署了本身的toString
方法,用来将一个数值转为字符串形式。
(10).toString() // "10"
复制代码
Number.prototype.toFixed()
toFixed()
方法先将一个数转为指定位数的小数,而后返回这个小数对应的字符串。
(10).toFixed(2) // "10.00"
复制代码
因为浮点数的缘由,小数5
的四舍五入是不肯定的,使用的时候必须当心。
(10.055).toFixed(2) // 10.05
(10.005).toFixed(2) // 10.01
复制代码
Number.prototype.toExponential()
toExponential
方法用于将一个数转为科学计数法形式。
toExponential
方法的参数是小数点后有效数字的位数,范围为0到20,超出这个范围,会抛出一个 RangeError 错误。
Number.prototype.toPrecision()
toPrecision
方法用于将一个数转为指定位数的有效数字。
(12.34).toPrecision(1) // "1e+1"
(12.34).toPrecision(2) // "12"
(12.34).toPrecision(3) // "12.3"
(12.34).toPrecision(4) // "12.34"
(12.34).toPrecision(5) // "12.340"
复制代码
toPrecision
方法的参数为有效数字的位数,范围是1到21,超出这个范围会抛出 RangeError 错误。
String.fromCharCode()
String
对象提供的静态方法(即定义在对象自己,而不是定义在对象实例的方法),主要是String.fromCharCode()
。该方法的参数是一个或多个数值,表明 Unicode 码点,返回值是这些码点组成的字符串。
charAt
方法返回指定位置的字符,参数是从0
开始编号的位置。
若是参数为负数,或大于等于字符串的长度,charAt
返回空字符串。
charCodeAt
方法返回字符串指定位置的 Unicode 码点(十进制表示),至关于String.fromCharCode()
的逆操做。
concat
方法用于链接两个字符串,返回一个新字符串,不改变原字符串。
slice
方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。
substring
方法用于从原字符串取出子字符串并返回,不改变原字符串,跟slice
方法很相像。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置(返回结果不含该位置)
substring
方法用于从原字符串取出子字符串并返回,不改变原字符串,跟slice
方法很相像。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置(返回结果不含该位置)
indexOf
方法用于肯定一个字符串在另外一个字符串中第一次出现的位置,返回结果是匹配开始的位置。若是返回-1
,就表示不匹配。
trim
方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。
该方法去除的不只是空格,还包括制表符(\t
、\v
)、换行符(\n
)和回车符(\r
)。
'\r\nabc \t'.trim() // 'abc'
复制代码
toLowerCase
方法用于将一个字符串所有转为小写,toUpperCase
则是所有转为大写。它们都返回一个新字符串,不改变原字符串。
match
方法用于肯定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。若是没有找到匹配,则返回null
。
search
方法的用法基本等同于match
,可是返回值为匹配的第一个位置。若是没有找到匹配,则返回-1
。
replace
方法用于替换匹配的子字符串,通常状况下只替换第一个匹配(除非使用带有g
修饰符的正则表达式)。
split
方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。
上面代码中,split
方法的第二个参数,决定了返回数组的成员数。
split
方法还可使用正则表达式做为参数,详见《正则表达式》一节。
Date.parse()方法解析的字符串,均可以看成Date构造函数的参数
new Date('2013-2-15')
new Date('2013/2/15')
new Date('02/15/2013')
new Date('2013-FEB-15')
new Date('FEB, 15, 2013')
new Date('FEB 15, 2013')
new Date('February, 15, 2013')
new Date('February 15, 2013')
new Date('15 Feb 2013')
new Date('15, February, 2013')
复制代码
多参数模式
new Date(2013, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1, 0, 0, 0, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
复制代码
上面代码中,无论有几个参数,返回的都是2013年1月1日零点。
最后,各个参数的取值范围以下。
2000
。若是写成两位数或个位数,则加上1900
,即10
表明1910年。若是是负数,表示公元前。0
表示一月,依次类推,11
表示12月。1
到31
。0
到23
。0
到59
。0
到59
0
到999
。var d1 = new Date(2000, 2, 1);
var d2 = new Date(2000, 3, 1);
d2 - d1
// 2678400000
d2 + d1
// "Sat Apr 01 2000 00:00:00 GMT+0800 (CST)Wed Mar 01 2000 00:00:00 GMT+0800 (CST)"
复制代码
Date.now
方法返回当前时间距离时间零点(1970年1月1日 00:00:00 UTC)的毫秒数,至关于 Unix 时间戳乘以1000。
Date.parse
方法用来解析日期字符串,返回该时间距离时间零点(1970年1月1日 00:00:00)的毫秒数。
Date.UTC
方法接受年、月、日等变量做为参数,返回该时间距离时间零点(1970年1月1日 00:00:00 UTC)的毫秒数。
toJSON
方法返回一个符合 JSON 格式的 ISO 日期字符串,与toISOString
方法的返回结果彻底相同。
toDateString
方法返回日期字符串(不含小时、分和秒)。
toTimeString
方法返回时间字符串(不含年月日)。
Date.prototype.toLocaleString()
:完整的本地时间。Date.prototype.toLocaleDateString()
:本地日期(不含小时、分和秒)。Date.prototype.toLocaleTimeString()
:本地时间(不含年月日)。var d = new Date(2013, 0, 1);
// 时间格式
// 下面的设置是,星期和月份为完整文字,年份和日期为数字
d.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
})
// "Tuesday, January 1, 2013"
// 指定时区
d.toLocaleTimeString('en-US', {
timeZone: 'UTC',
timeZoneName: 'short'
})
// "4:00:00 PM UTC"
d.toLocaleTimeString('en-US', {
timeZone: 'Asia/Shanghai',
timeZoneName: 'long'
})
// "12:00:00 AM China Standard Time"
// 小时周期为12仍是24
d.toLocaleTimeString('en-US', {
hour12: false
})
// "00:00:00"
d.toLocaleTimeString('en-US', {
hour12: true
})
// "12:00:00 AM"
复制代码
getTime()
:返回实例距离1970年1月1日00:00:00的毫秒数,等同于valueOf
方法。getDate()
:返回实例对象对应每月的几号(从1开始)。getDay()
:返回星期几,星期日为0,星期一为1,以此类推。getFullYear()
:返回四位的年份。getMonth()
:返回月份(0表示1月,11表示12月)。getHours()
:返回小时(0-23)。getMilliseconds()
:返回毫秒(0-999)。getMinutes()
:返回分钟(0-59)。getSeconds()
:返回秒(0-59)。getTimezoneOffset()
:返回当前时间与 UTC 的时区差别,以分钟表示,返回结果考虑到了夏令时因素。面这些get*
方法返回的都是当前时区的时间,Date
对象还提供了这些方法对应的 UTC 版本,用来返回 UTC 时间。
getUTCDate()
getUTCFullYear()
getUTCMonth()
getUTCDay()
getUTCHours()
getUTCMinutes()
getUTCSeconds()
getUTCMilliseconds()
setDate(date)
:设置实例对象对应的每月的几号(1-31),返回改变后毫秒时间戳。setFullYear(year [, month, date])
:设置四位年份。setHours(hour [, min, sec, ms])
:设置小时(0-23)。setMilliseconds()
:设置毫秒(0-999)。setMinutes(min [, sec, ms])
:设置分钟(0-59)。setMonth(month [, date])
:设置月份(0-11)。setSeconds(sec [, ms])
:设置秒(0-59)。setTime(milliseconds)
:设置毫秒时间戳。set*
系列方法除了setTime()
,都有对应的 UTC 版本,即设置 UTC 时区的时间。
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
JavaScript 的正则表达式体系是参照 Perl 5 创建的
新建正则表达式有两种方法。一种是使用字面量,以斜杠表示开始和结束。
var regex = /xyz/;
复制代码
另外一种是使用RegExp
构造函数。
var regex = new RegExp('xyz');
复制代码
它们的主要区别是,第一种方法在引擎编译代码时,就会新建正则表达式,第二种方法在运行时新建正则表达式,因此前者的效率较高。并且,前者比较便利和直观,因此实际应用中,基本上都采用字面量定义正则表达式。
RegExp
构造函数还能够接受第二个参数,表示修饰符(详细解释见下文)。
var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
复制代码
RegExp.prototype.ignoreCase
:返回一个布尔值,表示是否设置了i
修饰符。RegExp.prototype.global
:返回一个布尔值,表示是否设置了g
修饰符。RegExp.prototype.multiline
:返回一个布尔值,表示是否设置了m
修饰符。RegExp.prototype.flags
:返回一个字符串,包含了已经设置的全部修饰符,按字母排序。上面四个属性都是只读的。
var r = /abc/igm;
r.ignoreCase // true
r.global // true
r.multiline // true
r.flags // 'gim'
复制代码
RegExp.prototype.lastIndex
:返回一个整数,表示下一次开始搜索的位置。该属性可读写,可是只在进行连续搜索时有意义,详细介绍请看后文。RegExp.prototype.source
:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。var r = /abc/igm;
r.lastIndex // 0
r.source // "abc"
复制代码
正则实例对象的test
方法返回一个布尔值,表示当前模式是否能匹配参数字符串。
/cat/.test('cats and dogs') // 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
修饰符时,正则表达式内部会记住上一次的lastIndex
属性,这时不该该更换所要匹配的字符串,不然会有一些难以察觉的错误。
正则实例对象的exec
方法,用来返回匹配结果。若是发现匹配,就返回一个数组,成员是匹配成功的子字符串,不然返回null
。
var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
r1.exec(s) // ["x"]
r2.exec(s) // null
复制代码
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.
复制代码
下面是一个网页模板替换的例子。
var prices = {
'p1': '$1.99',
'p2': '$9.99',
'p3': '$5.00'
};
var template = '<span id="p1"></span>'
+ '<span id="p2"></span>'
+ '<span id="p3"></span>';
template.replace(
/(<span id=")(.*?)(">)(<\/span>)/g,
function(match, $1, $2, $3, $4){
return $1 + $2 + $3 + prices[$2] + $4;
}
);
// "<span id="p1">$1.99</span><span id="p2">$9.99</span><span id="p3">$5.00</span>"
复制代码
上面代码的捕捉模式中,有四个括号,因此会产生四个组匹配,在匹配函数中用$1
到$4
表示。匹配函数的做用是将价格插入模板中。
JSON 格式(JavaScript Object Notation 的缩写)是一种用于数据交换的文本格式,2001年由 Douglas Crockford 提出,目的是取代繁琐笨重的 XML 格式。
每一个 JSON 对象就是一个值,多是一个数组或对象,也多是一个原始类型的值。总之,只能是一个值,不能是两个或更多的值。
JSON 对值的类型和格式有严格的规定。
- 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。
- 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和
null
(不能使用NaN
,Infinity
,-Infinity
和undefined
)。- 字符串必须使用双引号表示,不能使用单引号。
- 对象的键名必须放在双引号里面。
- 数组或对象最后一个成员的后面,不能加逗号。
JSON.stringify
方法用于将一个值转为 JSON 字符串。该字符串符合 JSON 格式,而且能够被JSON.parse
方法还原。
若是对象的属性是undefined
、函数或 XML 对象,该属性会被JSON.stringify
过滤。
若是数组的成员是undefined
、函数或 XML 对象,则这些值被转成null
。
JSON.stringify
方法还能够接受一个数组,做为第二个参数,指定须要转成字符串的属性。
var obj = {
'prop1': 'value1',
'prop2': 'value2',
'prop3': 'value3'
};
var selectedProperties = ['prop1', 'prop2'];
JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"
复制代码
这个相似白名单的数组,只对对象的属性有效,对数组无效。
第二个参数还能够是一个函数,用来更改JSON.stringify
的返回值。
JSON.stringify
还能够接受第三个参数,用于增长返回的 JSON 字符串的可读性。若是是数字,表示每一个属性前面添加的空格(最多不超过10个);若是是字符串(不超过10个字符),则该字符串会添加在每行前面。
JSON.stringify({ p1: 1, p2: 2 }, null, 2);
/* "{ "p1": 1, "p2": 2 }" */
JSON.stringify({ p1:1, p2:2 }, null, '|-');
/* "{ |-"p1": 1, |-"p2": 2 }" */
复制代码
若是参数对象有自定义的toJSON
方法,那么JSON.stringify
会使用这个方法的返回值做为参数,而忽略原对象的其余属性。
var user = {
firstName: '三',
lastName: '张',
get fullName(){
return this.lastName + this.firstName;
},
toJSON: function () {
return {
name: this.lastName + this.firstName
};
}
};
JSON.stringify(user)
// "{"name":"张三"}"
复制代码
toJSON
方法的一个应用是,将正则对象自动转为字符串。由于JSON.stringify
默认不能转换正则对象,可是设置了toJSON
方法之后,就能够转换正则对象了。
var obj = {
reg: /foo/
};
// 不设置 toJSON 方法时
JSON.stringify(obj) // "{"reg":{}}"
// 设置 toJSON 方法时
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // ""/foo/""
复制代码
为了处理解析错误,能够将JSON.parse
方法放在try...catch
代码块中。
try {
JSON.parse("'String'");
} catch(e) {
console.log('parsing error');
}
复制代码
JSON.parse
方法能够接受一个处理函数,做为第二个参数,用法与JSON.stringify
方法相似。
function f(key, value) {
if (key === 'a') {
return value + 10;
}
return value;
}
JSON.parse('{"a": 1, "b": 2}', f)
// {a: 11, b: 2}
复制代码
能够作反向操做