标准库

Object 对象

JavaScript 的所有其他对象都继承自Object对象,即那些对象都是Object的实例。

Object对象的原生方法分成两类:Object本身的方法与Object的实例方法。
Object对象本身的方法

所谓“本身的方法”就是直接定义在Object对象的方法。

Object.print = function (o) { console.log(o) };
上面代码中,print方法就是直接定义在Object对象上。

Object的实例方法

所谓实例方法就是定义在Object原型对象Object.prototype上的方法。
它可以被Object实例直接使用。

Object.prototype.print = function () {
  console.log(this);
};

var obj = new Object();
obj.print() // Object

凡是定义在Object.prototype对象上面的属性和方法,
将被所有实例对象共享就可以了。

Object()

Object本身是一个函数,可以当作工具方法使用,将任意值转为对象。
这个方法常用于保证某个值一定是对象。

如果参数为空(或者为undefined和null),Object()返回一个空对象。

var obj = Object();
// 等同于
var obj = Object(undefined);
var obj = Object(null);

obj instanceof Object // true

instanceof运算符用来验证,一个对象是否为指定的构造函数的实例。
obj instanceof Object返回true,就表示obj对象是Object的实例

如果参数是原始类型的值,Object方法将其转为对应的包装对象的实例
var obj = Object(1);
obj instanceof Object // true
obj instanceof Number // true

如果Object方法的参数是一个对象,它总是返回该对象,即不用转换。

var arr = [];
var obj = Object(arr); // 返回原数组
obj === arr // true

Object构造函数

Object构造函数的首要用途,是直接通过它来生成新对象。

通过var obj = new Object()的写法生成新对象,与字面量的写法
var obj = {}是等价的。或者说,后者只是前者的一种简便写法。

Object 的静态方法

所谓“静态方法”,是指部署在Object对象自身的方法。

Object.keys方法和Object.getOwnPropertyNames方法都用来遍历对象的属性。
var obj = {
  p1: 123,
  p2: 456
};

Object.keys(obj) // ["p1", "p2"]
Object.getOwnPropertyNames(obj) // ["p1", "p2"]

对于一般的对象来说,Object.keys()和Object.getOwnPropertyNames()返回
的结果是一样的。只有涉及不可枚举属性时,才会有不一样的结果。Object.keys方
法只返回可枚举的属性,Object.getOwnPropertyNames方法还返回不可枚举的属性
名。

var a = ['Hello', 'World'];

Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]
上面代码中,数组的length属性是不可枚举的属性,所以只出现在
Object.getOwnPropertyNames方法的返回结果中。

其他方法

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 的实例方法

除了静态方法,还有不少方法定义在Object.prototype对象。它们称为实例方法,
所有Object的实例对象都继承了这些方法。

Object实例对象的方法,主要有以下六个。

Object.prototype.valueOf():返回当前对象对应的值。
Object.prototype.toString():返回当前对象对应的字符串形式。
Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。
Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的
属性,还是继承自原型对象的属性。
Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。
Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。

属性描述对象

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属性控制了属性描述对象的可写性。

(5get

get是一个函数,表示该属性的取值函数(getter),默认为undefined。

(6set

set是一个函数,表示该属性的存值函数(setter),默认为undefined。

**Object.getOwnPropertyDescriptor() **

Object.getOwnPropertyDescriptor()方法可以获取属性描述对象。
它的第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名。

var obj = { p: 'a' };

Object.getOwnPropertyDescriptor(obj, 'p')
// Object { value: "a",
//   writable: true,
//   enumerable: true,
//   configurable: true
// }

Object.getOwnPropertyDescriptor()方法只能用于对象自身的属性,不能用于
继承的属性

Object.getOwnPropertyNames()

Object.getOwnPropertyNames方法返回一个数组,成员是参数对象自身的全部属性
的属性名,不管该属性是否可遍历。

var obj = Object.defineProperties({}, {
  p1: { value: 1, enumerable: true },
  p2: { value: 2, enumerable: false }
});

Object.getOwnPropertyNames(obj)
// ["p1", "p2"]

这跟Object.keys的行为不同,Object.keys只返回对象自身的可遍历属性的全部
属性名。
Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ 'length' ]

Object.keys(Object.prototype) // []
Object.getOwnPropertyNames(Object.prototype)
// ['hasOwnProperty',
//  'valueOf',
//  'constructor',
//  'toLocaleString',
//  'isPrototypeOf',
//  'propertyIsEnumerable',
//  'toString']

Object.defineProperty(),Object.defineProperties()

Object.defineProperty()方法允许通过属性描述对象,定义或修改一个属性,
然后返回修改后的对象,它的用法如下。

Object.defineProperty(object, propertyName, attributesObject)
Object.defineProperty方法接受三个参数,依次如下。

object:属性所在的对象
propertyName:字符串,表示属性名
attributesObject:属性描述对象

举例来说,定义obj.p可以写成下面这样。

var obj = Object.defineProperty({}, 'p', {
  value: 123,
  writable: false,
  enumerable: true,
  configurable: false
});

obj.p // 123

obj.p = 246;
obj.p // 123

如果一次性定义或修改多个属性,可以使用Object.defineProperties()方法。

var obj = Object.defineProperties({}, {
  p1: { value: 123, enumerable: true },
  p2: { value: 'abc', enumerable: true },
  p3: { get: function () { return this.p1 + this.p2 },
    enumerable:true,
    configurable:true
  }
});

obj.p1 // 123
obj.p2 // "abc"
obj.p3 // "123abc"

注意,一旦定义了取值函数get(或存值函数set),就不能将writable属性设
为true,或者同时定义value属性,否则会报错。

Object.prototype.propertyIsEnumerable()

实例对象的propertyIsEnumerable()方法返回一个布尔值,用来判断某个属性
是否可遍历。注意,这个方法只能用于判断对象自身的属性,对于继承的属性一律
返回falsevar obj = {};
obj.p = 123;

obj.propertyIsEnumerable('p') // true
obj.propertyIsEnumerable('toString') // false
上面代码中,obj.p是可遍历的,而obj.toString是继承的属性。

存取器

除了直接定义以外,属性还可以用存取器(accessor)定义。其中,存值函数称为
setter,使用属性描述对象的set属性;取值函数称为getter,使用属性描述对象
的get属性。

一旦对目标属性定义了存取器,那么存取的时候,都将执行对应的函数。利用这个
功能,可以实现许多高级特性,比如定制属性的读取和赋值行为。

var obj = Object.defineProperty({}, 'p', {
  get: function () {
    return 'getter';
  },
  set: function (value) {
    console.log('setter: ' + value);
  }
});

obj.p // "getter"
obj.p = 123 // "setter: 123"
上面代码中,obj.p定义了getset属性。obj.p取值时,就会调用get;赋值时,
就会调用set。

JavaScript 还提供了存取器的另一种写法。

// 写法二
var obj = {
  get p() {
    return 'getter';
  },
  set p(value) {
    console.log('setter: ' + value);
  }
};
上面两种写法,虽然属性p的读取和赋值行为是一样的,但是有一些细微的区别。
第一种写法,属性p的configurable和enumerable都为false,从而导致属性p
是不可遍历的;第二种写法,属性p的configurable和enumerable都为true,
因此属性p是可遍历的。实际开发中,写法二更常用。

注意,取值函数get不能接受参数,存值函数set只能接受一个参数(即属性的值。

控制对象状态

有时需要冻结对象的读写状态,防止对象被改变。JavaScript 提供了三种冻结方法,
最弱的一种是Object.preventExtensions,其次是Object.seal,最强的是
Object.freeze。
1.Object.preventExtensions()
Object.preventExtensions方法可以使得一个对象无法再添加新的属性。
var obj = new Object();
Object.preventExtensions(obj);

Object.defineProperty(obj, 'p', {
  value: 'hello'
});
// TypeError: Cannot define property:p, object is not extensible

obj.p = 1;
obj.p // undefined

2.Object.isExtensible()
Object.isExtensible方法用于检查一个对象是否使用了
Object.preventExtensions方法。也就是说,检查是否可以为一个对象添加属性

var obj = new Object();

Object.isExtensible(obj) // true
Object.preventExtensions(obj);
Object.isExtensible(obj) // false
上面代码中,对obj对象使用Object.preventExtensions方法以后,再使用
Object.isExtensible方法,返回false,表示已经不能添加新属性了

3.Object.seal()
Object.seal方法使得一个对象既无法添加新属性,也无法删除旧属性。
var obj = { p: 'hello' };
Object.seal(obj);

delete obj.p;
obj.p // "hello"

obj.x = 'world';
obj.x // undefined
Object.seal只是禁止新增或删除属性,并不影响修改某个属性的值。

4.Object.isSealed() 
Object.isSealed方法用于检查一个对象是否使用了Object.seal方法。

5.Object.freeze() 

Object.freeze方法可以使得一个对象无法添加新属性、无法删除旧属性、也无法
改变属性的值,使得这个对象实际上变成了常量。

6.Object.isFrozen()

Object.isFrozen方法用于检查一个对象是否使用了Object.freeze方法

局限性

上面的三个方法锁定对象的可写性有一个漏洞:可以通过改变原型对象,来为对象增加
属性。

var obj = new Object();
Object.preventExtensions(obj);

var proto = Object.getPrototypeOf(obj);
proto.t = 'hello';
obj.t
// hello
上面代码中,对象obj本身不能新增属性,但是可以在它的原型对象上新增属性,
就依然能够在obj上读到。

另外一个局限是,如果属性值是对象,上面这些方法只能冻结属性指向的对象,而不能
冻结对象本身的内容。

var obj = {
  foo: 1,
  bar: ['a', 'b']
};
Object.freeze(obj);

obj.bar.push('c');
	obj.bar // ["a", "b", "c"]

Array 对象

构造函数

Array是 JavaScript 的原生对象,同时也是一个构造函数,可以用它生成
新的数组。

var arr = new Array(2);
// 等同于
var arr = Array(2);

arr.length // 2
arr // [ empty x 2 ]

静态方法
1.Array.isArray()

Array.isArray方法返回一个布尔值,表示参数是否为数组。它可以弥补typeof
运算符的不足。

var arr = [1, 2, 3];

typeof arr // "object"
Array.isArray(arr) // true

实例方法
1.valueOf(),toString()


valueOf方法是一个所有对象都拥有的方法,表示对该对象求值。不同对象的valueOf
方法不尽一致,数组的valueOf方法返回数组本身。

var arr = [1, 2, 3];
arr.valueOf() // [1, 2, 3]
toString方法也是对象的通用方法,数组的toString方法返回数组的字符串形式。

var arr = [1, 2, 3];
arr.toString() // "1,2,3"

var arr = [1, 2, 3, [4, 5, 6]];
arr.toString() // "1,2,3,4,5,6"

2.push(),pop()


push方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。
注意,该方法会改变原数组。

var arr = [];

arr.push(1) // 1
arr.push('a') // 2
arr.push(true, {}) // 4
arr // [1, 'a', true, {}]

pop方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。

var arr = ['a', 'b', 'c'];

arr.pop() // 'c'
arr // ['a', 'b']
对空数组使用pop方法,不会报错,而是返回undefined。

3.shift(),unshift()


shift()方法用于删除数组的第一个元素,并返回该元素。该方法会改变原数组。

var a = ['a', 'b', 'c'];

a.shift() // 'a'
a // ['b', 'c']

unshift()方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。
注意,该方法会改变原数组。

var a = ['a', 'b', 'c'];

a.unshift('x'); // 4
a // ['x', 'a', 'b', 'c']
unshift()方法可以接受多个参数,这些参数都会添加到目标数组头部。

var arr = [ 'c', 'd' ];
arr.unshift('a', 'b') // 4
arr // [ 'a', 'b', 'c', 'd' ]

4.join()


join()方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果
不提供参数,默认用逗号分隔。
数组成员是undefined或null或空位,会被转成空字符串。

[undefined, null].join('#')
// '#'

['a',, 'b'].join('-')
// 'a--b'

通过call方法,这个方法也可以用于字符串或类似数组的对象。

Array.prototype.join.call('hello', '-')
// "h-e-l-l-o"

var obj = { 0: 'a', 1: 'b', length: 2 };
Array.prototype.join.call(obj, '-')
// 'a-b'

5.concat()


concat方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,
然后返回一个新数组,原数组不变。

['hello'].concat(['world'])
// ["hello", "world"]

除了数组作为参数,concat也接受其他类型的值作为参数,添加到目标数组尾部。

[1, 2, 3].concat(4, 5, 6)
// [1, 2, 3, 4, 5, 6]

如果数组成员包括对象,concat方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,
指的是新数组拷贝的是对象的引用。

var obj = { a: 1 };
var oldArray = [obj];

var newArray = oldArray.concat();

obj.a = 2;
newArray[0].a // 2
上面代码中,原数组包含一个对象,concat方法生成的新数组包含这个对象的引用。
所以,改变原对象以后,新数组跟着改变。

6.reverse()


reverse方法用于颠倒排列数组元素,返回改变后的数组。注意,该方法
将改变原数组。

var a = ['a', 'b', 'c'];

a.reverse() // ["c", "b", "a"]
a // ["c", "b", "a"]

7.slice()


slice()方法用于提取目标数组的一部分,返回一个新数组,原数组不变。

arr.slice(start, end);
它的第一个参数为起始位置(从0开始,会包括在返回的新数组之中),第二个参数为
终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原
数组的最后一个成员。

var a = ['a', 'b', 'c'];

a.slice(0) // ["a", "b", "c"]
a.slice(1, 2) // ["b"]
a.slice() // ["a", "b", "c"]

如果slice()方法的参数是负数,则表示倒数计算的位置。

var a = ['a', 'b', 'c'];
a.slice(-2) // ["b", "c"]
a.slice(-2, -1) // ["b"]
上面代码中,-2表示倒数计算的第二个位置,-1表示倒数计算的第一个位置。

如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。

slice()方法的一个重要应用,是将类似数组的对象转为真正的数组。
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })
// ['a', 'b']

8.splice()

splice()方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组
成员,返回值是被删除的元素。注意,该方法会改变原数组。

arr.splice(start, count, addElement1, addElement2, ...);
splice的第一个参数是删除的起始位置(从0开始),第二个参数是被删除的元素个
数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。

var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(4, 2) // ["e", "f"]
a // ["a", "b", "c", "d"]

9.sort()

sort方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。
['d', 'c', 'b', 'a'].sort()
// ['a', 'b', 'c', 'd']

[4, 3, 2, 1].sort()
// [1, 2, 3, 4]

sort()方法不是按照大小排序,而是按照字典顺序。也就是说,数值会被先转成字
符串,再按照字典顺序进行比较

如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数。

[10111, 1101, 111].sort(function (a, b) {
  return a - b;
})
// [111, 1101, 10111]
上面代码中,sort的参数函数本身接受两个参数,表示进行比较的两个数组成员。
如果该函数的返回值大于0,表示第一个成员排在第二个成员后面;其他情况下,都
是第一个元素排在第二个元素前面。

注意,自定义的排序函数应该返回数值,否则不同的浏览器可能有不同的实现,不能
保证结果都一致。

// bad
[1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a > b)

// good
[1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a - b)

10.map()

map方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个
新数组返回。

var numbers = [1, 2, 3];

numbers.map(function (n) {
  return n + 1;
});
// [2, 3, 4]
map方法接受一个函数作为参数。该函数调用时,map方法向它传入三个参数:
当前成员、当前位置和数组本身。

[1, 2, 3].map(function(elem, index, arr) {
  return elem * index;
});
// [0, 2, 6]

上面代码中,map方法的回调函数有三个参数,elem为当前成员的值,index为当前
成员的位置,arr为原数组([1, 2, 3])

map方法还可以接受第二个参数,用来绑定回调函数内部的this变量。

var arr = ['a', 'b', 'c'];

[1, 2].map(function (e) {
  return this[e];
}, arr)
// ['b', 'c']
上面代码通过map方法的第二个参数,将回调函数内部的this对象,指向arr数组。

11.forEach()

forEach方法与map方法很相似,也是对数组的所有成员依次执行参数函数。但是,
forEach方法不返回值,只用来操作数据

forEach的用法与map方法一致,参数是一个函数,该函数同样接受三个参数:
当前值、当前位置、整个数组。

forEach方法也可以接受第二个参数,绑定参数函数的this变量

var out = [];

[1, 2, 3].forEach(function(elem) {
  this.push(elem * elem);
}, out);

out // [1, 4, 9]

12.filter()

filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。

它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一
个新数组返回。该方法不会改变原数组。

[1, 2, 3, 4, 5].filter(function (elem) {
  return (elem > 3);
})
// [4, 5]
上面代码将大于3的数组成员,作为一个新数组返回。

filter方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。

filter方法还可以接受第二个参数,用来绑定参数函数内部的this变量。

var obj = { MAX: 3 };
var myFilter = function (item) {
  if (item > this.MAX) return true;
};

var arr = [2, 8, 3, 4, 1, 3, 2, 9];
arr.filter(myFilter, obj) // [8, 4, 9]

13.some(),every()

它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:
当前成员、当前位置和整个数组,然后返回一个布尔值。

some方法是只要一个成员的返回值是true,则整个some方法的返回值就是true,
否则返回falsevar arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
  return elem >= 3;
});
// true

every方法是所有成员的返回值都是true,整个every方法才返回true,
否则返回falsevar arr = [1, 2, 3, 4, 5];
arr.every(function (elem, index, arr) {
  return elem >= 3;
});
// false

注意,对于空数组,some方法返回false,every方法返回true,
回调函数都不会执行。

function isEven(x) { return x % 2 === 0 }

[].some(isEven) // false
[].every(isEven) // true

some和every方法还可以接受第二个参数,用来绑定参数函数内部的this变量。

14.reduce(),reduceRight()

reduce方法和reduceRight方法依次处理数组的每个成员,最终累计为一个值。
它们的差别是,reduce是从左到右处理(从第一个成员到最后一个成员),
reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样。
[1, 2, 3, 4, 5].reduce(function (a, b) {
  console.log(a, b);
  return a + b;
})
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15

reduce方法和reduceRight方法的第一个参数都是一个函数。该函数接受以下四个
参数。

累积变量,默认为数组的第一个成员
当前变量,默认为数组的第二个成员
当前位置(从0开始)
原数组
这四个参数之中,只有前两个是必须的,后两个则是可选的。

如果要对累积变量指定初值,可以把它放在reduce方法和reduceRight方法的
第二个参数。

[1, 2, 3, 4, 5].reduce(function (a, b) {
  return a + b;
}, 10);
// 25

上面代码指定参数a的初值为10,所以数组从10开始累加,最终结果为25。注意,
这时b是从数组的第一个成员开始遍历。

15.indexOf(),lastIndexOf()

indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1var a = ['a', 'b', 'c'];

a.indexOf('b') // 1
a.indexOf('y') // -1
indexOf方法还可以接受第二个参数,表示搜索的开始位置。

['a', 'b', 'c'].indexOf('a', 1) // -1


lastIndexOf方法返回给定元素在数组中最后一次出现的位置,如果没有出现
则返回-1var a = [2, 5, 9, 2];
a.lastIndexOf(2) // 3
a.lastIndexOf(7) // -1
注意,这两个方法不能用来搜索NaN的位置,即它们无法确定数组成员是否包含NaN[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1

16.链式使用

上面这些数组方法之中,有不少返回的还是数组,所以可以链式使用。

var users = [
  {name: 'tom', email: 'tom@example.com'},
  {name: 'peter', email: 'peter@example.com'}
];

users
.map(function (user) {
  return user.email;
})
.filter(function (email) {
  return /^t/.test(email);
})
.forEach(function (email) {
  console.log(email);
});
// "tom@example.com"

包装对象

定义

对象是 JavaScript 语言最主要的数据类型,三种原始类型的值——数值、字符串、
布尔值——在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”。

所谓“包装对象”,指的是与数值、字符串、布尔值分别相对应的Number、String、
Boolean三个原生对象。这三个原生对象可以把原始类型的值变成(包装成)对象。

var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);

typeof v1 // "object"
typeof v2 // "object"
typeof v3 // "object"

v1 === 123 // false
v2 === 'abc' // false
v3 === true // false

Number、String和Boolean这三个原生对象,如果不作为构造函数调用(即调用时
不加new),而是作为普通函数调用,常常用于将任意类型的值转为数值、字符串和布
尔值。

// 字符串转为数值
Number('123') // 123

// 数值转为字符串
String(123) // "123"

// 数值转为布尔值
Boolean(123) // true
这三个对象作为构造函数使用(带有new)时,可以将原始类型的值转为对象;作为
普通函数使用时(不带有new),可以将任意类型的值,转为原始类型的值。

实例方法
三种包装对象各自提供了许多实例方法。这里介绍两种它们共同具有、从Object对象
继承的方法:valueOf()和toString()。

1.valueOf()

valueOf()方法返回包装对象实例对应的原始类型的值。

new Number(123).valueOf()  // 123
new String('abc').valueOf() // "abc"
new Boolean(true).valueOf() // true

2.toString()

toString()方法返回对应的字符串形式。

new Number(123).toString() // "123"
new String('abc').toString() // "abc"
new Boolean(true).toString() // "true"

原始类型与实例对象的自动转换

某些场合,原始类型的值会自动当作包装对象调用,即调用包装对象的属性和方法。
这时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,并在使用后立刻
销毁实例。

比如,字符串可以调用length属性,返回字符串的长度。

'abc'.length // 3
上面代码中,abc是一个字符串,本身不是对象,不能调用length属性。
JavaScript 引擎自动将其转为包装对象,在这个对象上调用length属性。
调用结束后,这个临时对象就会被销毁。这就叫原始类型与实例对象的自动转换。

// 等同于
var strObj = new String(str)
// String {
//  0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"
// }
strObj.length // 3

自动转换生成的包装对象是只读的,无法修改。所以,字符串无法添加新属性。

var s = 'Hello World';
s.x = 123;
s.x // undefined

自定义方法

除了原生的实例方法,包装对象还可以自定义方法和属性,供原始类型的值直接调用。

比如,我们可以新增一个double方法,使得字符串和数字翻倍。

String.prototype.double = function () {
  return this.valueOf() + this.valueOf();
};

'abc'.double()
// abcabc

Number.prototype.double = function () {
  return this.valueOf() + this.valueOf();
};

(123).double() // 246

Boolean 对象

Boolean对象是 JavaScript 的三个包装对象之一。作为构造函数,它主要用于
生成布尔值的包装对象实例。

var b = new Boolean(true);

typeof b // "object"
b.valueOf() // true

注意,false对应的包装对象实例,布尔运算结果也是trueif (new Boolean(false)) {
  console.log('true');
} // true

if (new Boolean(false).valueOf()) {
  console.log('true');
} // 无输出

Number 对象

1.静态属性

Number对象拥有以下一些静态属性(即直接定义在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

2.实例方法

1.Number.prototype.toString()
Number对象部署了自己的toString方法,用来将一个数值转为字符串形式。

(10).toString() // "10"

toString方法可以接受一个参数,表示输出的进制。如果省略这个参数,默认
将数值先转为十进制,再输出字符串;否则,就根据参数指定的进制,将一个数
字转化成某个进制的字符串。

(10).toString(2) // "1010"

2.Number.prototype.toFixed()
toFixed()方法先将一个数转为指定位数的小数,然后返回这个小数对应的字符串。

(10).toFixed(2) // "10.00"
10.005.toFixed(2) // "10.01"

toFixed()方法的参数为小数位数,有效范围为0100,超出这个范围将抛出 
RangeError 错误。

3.Number.prototype.toExponential()
toExponential方法用于将一个数转为科学计数法形式。

(10).toExponential()  // "1e+1"
(10).toExponential(1) // "1.0e+1"

4.Number.prototype.toPrecision()
Number.prototype.toPrecision()方法用于将一个数转为指定位数的有效数字。

(12.34).toPrecision(1) // "1e+1"
(12.34).toPrecision(2) // "12"

该方法用于四舍五入时不太可靠,跟浮点数不是精确储存有关。

(12.35).toPrecision(3) // "12.3"
(12.25).toPrecision(3) // "12.3"

5.Number.prototype.toLocaleString()
Number.prototype.toLocaleString()方法接受一个地区码作为参数,
返回一个字符串,表示当前数字在该地区的当地书写形式。

(123).toLocaleString('zh-Hans-CN-u-nu-hanidec')
// "一二三"
该方法还可以接受第二个参数配置对象,用来定制指定用途的返回字符串。
该对象的style属性指定输出样式,默认值是decimal,表示输出十进制形式。
如果值为percent,表示输出百分数。

(123).toLocaleString('zh-Hans-CN', { style: 'percent' })
// "12,300%"
如果style属性的值为currency,则可以搭配currency属性,输出指定格式的
货币字符串形式。

(123).toLocaleString('zh-Hans-CN', { style: 'currency', 
currency: 'CNY' })
// "¥123.00"

(123).toLocaleString('de-DE', { style: 'currency',
 currency: 'EUR' })
// "123,00 €"

(123).toLocaleString('en-US', { style: 'currency',
 currency: 'USD' })
// "$123.00"
如果Number.prototype.toLocaleString()省略了参数,则由浏览器自行
决定如何处理,通常会使用操作系统的地区设定。

自定义方法

与其他对象一样,Number.prototype对象上面可以自定义方法,被Number的
实例继承。

Number.prototype.add = function (x) {
  return this + x;
};

8['add'](2) // 10

String 对象

字符串对象是一个类似数组的对象(很像数组,但不是数组)。

new String('abc')
// String {0: "a", 1: "b", 2: "c", length: 3}

(new String('abc'))[1] // "b"

1.静态方法

1.String.fromCharCode()
String.fromCharCode()。该方法的参数是一个或多个数值,代表 Unicode 
码点,返回值是这些码点组成的字符串。

String.fromCharCode() // ""
String.fromCharCode(97) // "a"
String.fromCharCode(104, 101, 108, 108, 111)
// "hello"

2.实例属性
1.String.prototype.length

字符串实例的length属性返回字符串的长度。

'abc'.length // 3

实例方法
1.String.prototype.charAt()

charAt方法返回指定位置的字符,参数是从0开始编号的位置。

var s = new String('abc');

s.charAt(1) // "b"
s.charAt(s.length - 1) // "c"
这个方法完全可以用数组下标替代。

'abc'.charAt(1) // "b"
'abc'[1] // "b"

如果参数为负数,或大于等于字符串的长度,charAt返回空字符串。

'abc'.charAt(-1) // ""
'abc'.charAt(3) // ""

2.String.prototype.charCodeAt()

charCodeAt()方法返回字符串指定位置的 Unicode 码点(十进制表示),
相当于String.fromCharCode()的逆操作。

'abc'.charCodeAt(1) // 98
如果没有任何参数,charCodeAt返回首字符的 Unicode 码点。

'abc'.charCodeAt() // 97
如果参数为负数,或大于等于字符串的长度,charCodeAt返回NaN'abc'.charCodeAt(-1) // NaN
'abc'.charCodeAt(4) // NaN

3.String.prototype.concat()

concat方法用于连接两个字符串,返回一个新字符串,不改变原字符串。

var s1 = 'abc';
var s2 = 'def';

s1.concat(s2) // "abcdef"
s1 // "abc"
该方法可以接受多个参数。

'a'.concat('b', 'c') // "abc"

如果参数不是字符串,concat方法会将其先转为字符串,然后再连接。

var one = 1;
var two = 2;
var three = '3';

''.concat(one, two, three) // "123"

4.String.prototype.slice()

slice()方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个
参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。

'JavaScript'.slice(0, 4) // "Java"

5.String.prototype.substring()

substring方法用于从原字符串取出子字符串并返回,不改变原字符串,
跟slice方法很相像。它的第一个参数表示子字符串的开始位置,第二个
位置表示结束位置(返回结果不含该位置)。

'JavaScript'.substring(0, 4) // "Java"

如果第一个参数大于第二个参数,substring方法会自动更换两个参数的位置。

'JavaScript'.substring(10, 4) // "Script"
// 等同于
'JavaScript'.substring(4, 10) // "Script"

如果参数是负数,substring方法会自动将负数转为0'JavaScript'.substring(-3) // "JavaScript"
'JavaScript'.substring(4, -3) // "Java"

6.String.prototype.substr()

substr方法用于从原字符串取出子字符串并返回,不改变原字符串,
跟slice和substring方法的作用相同。

substr方法的第一个参数是子字符串的开始位置(从0开始计算),第二个
参数是子字符串的长度。

'JavaScript'.substr(4, 6) // "Script"

7.String.prototype.indexOf(),String.prototype.lastIndexOf()

indexOf方法用于确定一个字符串在另一个字符串中第一次出现的位置,
返回结果是匹配开始的位置。如果返回-1,就表示不匹配。

'hello world'.indexOf('o') // 4
'JavaScript'.indexOf('script') // -1
indexOf方法还可以接受第二个参数,表示从该位置开始向后匹配。

'hello world'.indexOf('o', 6) // 7
lastIndexOf方法的用法跟indexOf方法一致,主要的区别是lastIndexOf从尾
部开始匹配,indexOf则是从头部开始匹配。

'hello world'.lastIndexOf('o') // 7
另外,lastIndexOf的第二个参数表示从该位置起向前匹配。

'hello world'.lastIndexOf('o', 6) // 4

8.String.prototype.trim()

trim方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。

'  hello world  '.trim()
// "hello world"

该方法去除的不仅是空格,还包括制表符(\t、\v)、换行符(\n)和回车符(\r)

'\r\nabc \t'.trim() // 'abc'

9.String.prototype.toLowerCase(),String.prototype.toUpperCase()

toLowerCase方法用于将一个字符串全部转为小写,toUpperCase则是全部转为
大写。它们都返回一个新字符串,不改变原字符串。

'Hello World'.toLowerCase()
// "hello world"

'Hello World'.toUpperCase()
// "HELLO WORLD"

10.String.prototype.match()

match方法用于确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配
的第一个字符串。如果没有找到匹配,则返回null'cat, bat, sat, fat'.match('at') // ["at"]
'cat, bat, sat, fat'.match('xt') // null
返回的数组还有index属性和input属性,分别表示匹配字符串开始的位置和原始
字符串。

var matches = 'cat, bat, sat, fat'.match('at');
matches.index // 1
matches.input // "cat, bat, sat, fat"

11.String.prototype.search(),String.prototype.replace()

search方法的用法基本等同于match,但是返回值为匹配的第一个位置。如果没
有找到匹配,则返回-1'cat, bat, sat, fat'.search('at') // 1
replace方法用于替换匹配的子字符串,一般情况下只替换第一个匹配
(除非使用带有g修饰符的正则表达式)。

'aaa'.replace('a', 'b') // "baa"

12.String.prototype.split()

split方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。

'a|b|c'.split('|') // ["a", "b", "c"]
如果分割规则为空字符串,则返回数组的成员是原字符串的每一个字符。

'a|b|c'.split('') // ["a", "|", "b", "|", "c"]
如果省略参数,则返回数组的唯一成员就是原字符串。

'a|b|c'.split() // ["a|b|c"]
如果满足分割规则的两个部分紧邻着(即两个分割符中间没有其他字符),则返回
数组之中会有一个空字符串。

'a||c'.split('|') // ['a', '', 'c']
如果满足分割规则的部分处于字符串的开头或结尾(即它的前面或后面没有其他字符)
则返回数组的第一个或最后一个成员是一个空字符串。

'|b|c'.split('|') // ["", "b", "c"]
'a|b|'.split('|') // ["a", "b", ""]
split方法还可以接受第二个参数,限定返回数组的最大成员数。

'a|b|c'.split('|', 0) // []
'a|b|c'.split('|', 1) // ["a"]
'a|b|c'.split('|', 2) // ["a", "b"]

13.String.prototype.localeCompare()

localeCompare方法用于比较两个字符串。它返回一个整数,如果小于0,
表示第一个字符串小于第二个字符串;如果等于0,表示两者相等;如果大于0,
表示第一个字符串大于第二个字符串。

'apple'.localeCompare('banana') // -1
'apple'.localeCompare('apple') // 0

localeCompare还可以有第二个参数,指定所使用的语言(默认是英语),然后根据
该语言的规则进行比较。

'ä'.localeCompare('z', 'de') // -1
'ä'.localeCompare('z', 'sv') // 1
上面代码中,de表示德语,sv表示瑞典语。德语中,ä小于z,所以返回-1;瑞典语中
ä大于z,所以返回1

Math对象

Math是 JavaScript 的原生对象,提供各种数学功能。该对象不是构造函数,
不能生成实例,所有的属性和方法都必须在Math对象上调用。
1.静态属性


Math对象的静态属性,提供以下一些数学常数。

Math.E:常数e。
Math.LN22 的自然对数。
Math.LN1010 的自然对数。
Math.LOG2E:以 2 为底的e的对数。
Math.LOG10E:以 10 为底的e的对数。
Math.PI:常数π。
Math.SQRT1_20.5 的平方根。
Math.SQRT22 的平方根。

这些属性都是只读的,不能修改。

2.静态方法

Math对象提供以下一些静态方法。

Math.abs():绝对值
Math.ceil():向上取整
Math.floor():向下取整
Math.max():最大值
Math.min():最小值
Math.pow():幂运算
Math.sqrt():平方根
Math.log():自然对数
Math.exp():e的指数
Math.round():四舍五入
Math.random():随机数

三角函数方法

Math对象还提供一系列三角函数方法。

Math.sin():返回参数的正弦(参数为弧度值)
Math.cos():返回参数的余弦(参数为弧度值)
Math.tan():返回参数的正切(参数为弧度值)
Math.asin():返回参数的反正弦(返回值为弧度值)
Math.acos():返回参数的反余弦(返回值为弧度值)
Math.atan():返回参数的反正切(返回值为弧度值)

Date 对象

1.普通函数的用法

Date对象可以作为普通函数直接调用,返回一个代表当前时间的字符串。

Date()
// "Tue Dec 01 2015 09:34:43 GMT+0800 (CST)"
注意,即使带有参数,Date作为普通函数使用时,返回的还是当前时间。

Date(2000, 1, 1)
// "Tue Dec 01 2015 09:34:43 GMT+0800 (CST)"

2.构造函数的用法

Date实例有一个独特的地方。其他对象求值的时候,都是默认调用.valueOf()方法
但是Date实例求值的时候,默认调用的是toString()方法。这导致对Date实例求值
返回的是一个字符串,代表该实例对应的时间。
var today = new Date();

today
// "Tue Dec 01 2015 09:34:43 GMT+0800 (CST)"

// 等同于
today.toString()
// "Tue Dec 01 2015 09:34:43 GMT+0800 (CST)"


作为构造函数时,Date对象可以接受多种格式的参数,返回一个该参数
对应的时间实例。

// 参数为时间零点开始计算的毫秒数
new Date(1378218728000)
// Tue Sep 03 2013 22:32:08 GMT+0800 (CST)

// 参数为日期字符串
new Date('January 6, 2013');
// Sun Jan 06 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)

日期的运算

类型自动转换时,Date实例如果转为数值,则等于对应的毫秒数;如果转为字符串,
则等于对应的日期字符串。所以,两个日期实例对象进行减法运算时,返回的是它们
间隔的毫秒数;进行加法运算时,返回的是两个字符串连接而成的新字符串。

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)"

静态方法
1.Date.now()

Date.now方法返回当前时间距离时间零点(19701100:00:00 UTC)的
毫秒数,相当于 Unix 时间戳乘以1000。

Date.now() // 1364026285194

2.Date.parse()

Date.parse方法用来解析日期字符串,返回该时间距离时间零点
(19701100:00:00)的毫秒数。

日期字符串应该符合 RFC 2822ISO 8061 这两个标准,
即YYYY-MM-DDTHH:mm:ss.sssZ格式,其中最后的Z表示时区。
但是,其他格式也可以被解析,请看下面的例子。

Date.parse('Aug 9, 1995')
Date.parse('January 26, 2011 13:51:50')
Date.parse('Mon, 25 Dec 1995 13:30:00 GMT')
Date.parse('Mon, 25 Dec 1995 13:30:00 +0430')
Date.parse('2011-10-10')
Date.parse('2011-10-10T14:48:00')

3.Date.UTC()

Date.UTC方法接受年、月、日等变量作为参数,返回该时间距离时间零点
(19701100:00:00 UTC)的毫秒数。

// 格式
Date.UTC(year, month[, date[, hrs[, min[, sec[, ms]]]]])

// 用法
Date.UTC(2011, 0, 1, 2, 3, 4, 567)
// 1293847384567
该方法的参数用法与Date构造函数完全一致,比如月从0开始计算,日期从1开始
计算。区别在于Date.UTC方法的参数,会被解释为 UTC 时间(世界标准时间),
Date构造函数的参数会被解释为当前时区的时间。

实例方法

Date的实例对象,有几十个自己的方法,除了valueOf和toString,可以分为以下
三类。

to类:从Date对象返回一个字符串,表示指定的时间。
get类:获取Date对象的日期和时间。
set类:设置Date对象的日期和时间。

1.Date.prototype.valueOf()

valueOf方法返回实例对象距离时间零点(19701100:00:00 UTC)对应
的毫秒数,该方法等同于getTime方法。

var d = new Date();

d.valueOf() // 1362790014817
d.getTime() // 1362790014817
预期为数值的场合,Date实例会自动调用该方法,所以可以用下面的方法计算时间
的间隔。

var start = new Date();
// ...
var end = new Date();
var elapsed = end - start;

2.to 类方法

(1)Date.prototype.toString()
toString是默认的调用方法,所以如果直接读取Date实例,就相当于调用这个方法。
var d = new Date(2013, 0, 1);

d.toString()
// "Tue Jan 01 2013 00:00:00 GMT+0800 (CST)"2)Date.prototype.toUTCString()
toUTCString方法返回对应的 UTC 时间,也就是比北京时间晚8个小时。

(3)Date.prototype.toISOString()

toISOString方法返回对应时间的 ISO8601 写法。

var d = new Date(2013, 0, 1);

d.toISOString()
// "2012-12-31T16:00:00.000Z"
注意,toISOString方法返回的总是 UTC 时区的时间。

(4)Date.prototype.toJSON()

toJSON方法返回一个符合 JSON 格式的 ISO 日期字符串,与toISOString
方法的返回结果完全相同。

(5)Date.prototype.toDateString()
toDateString方法返回日期字符串(不含小时、分和秒)。

var d = new Date(2013, 0, 1);
d.toDateString() // "Tue Jan 01 2013"6)Date.prototype.toTimeString()

toTimeString方法返回时间字符串(不含年月日)。

var d = new Date(2013, 0, 1);
d.toTimeString() // "00:00:00 GMT+0800 (CST)"7)本地时间
以下三种方法,可以将 Date 实例转为表示本地时间的字符串。

Date.prototype.toLocaleString():完整的本地时间。
Date.prototype.toLocaleDateString():本地日期(不含小时、分和秒)。
Date.prototype.toLocaleTimeString():本地时间(不含年月日)。
下面是用法实例。

var d = new Date(2013, 0, 1);

d.toLocaleString()
// 中文版浏览器为"2013年1月1日 上午12:00:00"
// 英文版浏览器为"1/1/2013 12:00:00 AM"

d.toLocaleDateString()
// 中文版浏览器为"2013年1月1日"
// 英文版浏览器为"1/1/2013"

d.toLocaleTimeString()
// 中文版浏览器为"上午12:00:00"
// 英文版浏览器为"12:00:00 AM"

这两个参数中,locales是一个指定所用语言的字符串,options是一个配置对象。
下面是locales的例子,分别采用en-US和zh-CN语言设定。

var d = new Date(2013, 0, 1);

d.toLocaleString('en-US') // "1/1/2013, 12:00:00 AM"
d.toLocaleString('zh-CN') // "2013/1/1 上午12:00:00"

d.toLocaleDateString('en-US') // "1/1/2013"
d.toLocaleDateString('zh-CN') // "2013/1/1"

d.toLocaleTimeString('en-US') // "12:00:00 AM"
d.toLocaleTimeString('zh-CN') // "上午12:00:00"
options配置对象有以下属性。
dateStyle:可能的值为full、long、medium、short。
timeStyle:可能的值为full、long、medium、short。
month:可能的值为numeric、2-digit、long、short、narrow。
year:可能的值为numeric、2-digit。
weekday:可能的值为long、short、narrow。
day、hour、minute、second:可能的值为numeric、2-digit。
timeZone:可能的值为 IANA 的时区数据库。
timeZooneName:可能的值为long、short。
hour12:24小时周期还是12小时周期,可能的值为truefalse。
下面是用法实例。

var d = new Date(2013, 0, 1);

d.toLocaleDateString('en-US', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
})

3.get 类方法

Date对象提供了一系列get*方法,用来获取实例对象某个方面的值。

getTime():返回实例距离19701100: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*方法返回的都是整数,不同方法返回值的范围不一样。

分钟和秒:059
小时:023
星期:0(星期天)到 6(星期六)
日期:131
月份:0(一月)到 11(十二月)

var d = new Date('January 6, 2013');

d.getDate() // 6
d.getMonth() // 0
d.getFullYear() // 2013
d.getTimezoneOffset() // -480

4.set 类方法

Date对象提供了一系列set*方法,用来设置实例对象的各个方面。

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):设置毫秒时间戳。
这些方法基本是跟get*方法一一对应的,但是没有setDay方法,因为星期几是计
算出来的,而不是设置的。另外,需要注意的是,凡是涉及到设置月份,都是从0开
始算的,即01月,1112月。

var d = new Date ('January 6, 2013');

d // Sun Jan 06 2013 00:00:00 GMT+0800 (CST)
d.setDate(9) // 1357660800000
d // Wed Jan 09 2013 00:00:00 GMT+0800 (CST)

set类方法和get类方法,可以结合使用,得到相对时间。

var d = new Date();

// 将日期向后推1000天
d.setDate(d.getDate() + 1000);
// 将时间设为6小时后
d.setHours(d.getHours() + 6);
// 将年份设为去年
d.setFullYear(d.getFullYear() - 1);

RegExp 对象

RegExp对象提供正则表达式的功能。

新建正则表达式有两种方法。一种是使用字面量,以斜杠表示开始和结束。

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"

实例方法
1.RegExp.prototype.test()

正则实例对象的test方法返回一个布尔值,表示当前模式是否能匹配参数字符串。

/cat/.test('cats and dogs') // true
上面代码验证参数字符串之中是否包含cat,结果返回true

2.RegExp.prototype.exec()

正则实例对象的exec()方法,用来返回匹配结果。如果发现匹配,就返回一个数组,
成员是匹配成功的子字符串,否则返回nullvar s = '_x_x';
var r1 = /x/;
var r2 = /y/;

r1.exec(s) // ["x"]
r2.exec(s) // null

var s = '_x_x';
var r = /_(x)/;

r.exec(s) // ["_x", "x"]
上面代码的exec()方法,返回一个数组。第一个成员是整个匹配的结果,
第二个成员是圆括号匹配的结果。

exec()方法的返回数组还包含以下两个属性:

input:整个原字符串。
index:模式匹配成功的开始位置(从0开始计数)。

字符串的实例方法

字符串的实例方法之中,有4种与正则表达式有关。

String.prototype.match():返回一个数组,成员是所有匹配的子字符串。

var s = 'abba';
var r = /a/g;

s.match(r) // ["a", "a"]
r.exec(s) // ["a"]
String.prototype.search():按照给定的正则表达式进行搜索,返回一个
整数,表示匹配开始的位置。
'_x_x'.search(/x/)
// 1
String.prototype.replace():按照给定的正则表达式进行替换,返回替换
后的字符串。
String.prototype.split():按照给定规则进行字符串分割,返回一个数组,
包含分割后的各个成员。
'aaa'.replace(/a/, 'b') // "baa"
'aaa'.replace(/a/g, 'b') // "bbb"

修饰符

1)g 修饰符

默认情况下,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局
匹配(global)

(2)i 修饰符

默认情况下,正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写
(3)m 修饰符

m修饰符表示多行模式(multiline),会修改^和$的行为。默认情况下
(即不加m修饰符时),^和$匹配字符串的开始处和结尾处,加上m修饰符以后,
^和$还会匹配行首和行尾,即^和$会识别换行符(\n)。

JSON 对象

JSON对象是 JavaScript 的原生对象,用来处理 JSON 格式数据。
它有两个静态方法:JSON.stringify()和JSON.parse()。
JSON.stringify()

JSON.stringify方法用于将一个值转为 JSON 字符串。该字符串符合 JSON 格式,
并且可以被JSON.parse方法还原。

JSON.stringify('abc') // ""abc""
JSON.stringify(1) // "1"
JSON.stringify(false) // "false"
JSON.stringify([]) // "[]"
JSON.stringify({}) // "{}"

JSON.stringify([1, "false", false])
// '[1,"false",false]'

JSON.stringify({ name: "张三" })
// '{"name":"张三"}'

如果对象的属性是undefined、函数或 XML 对象,该属性会被
JSON.stringify过滤。

var obj = {
  a: undefined,
  b: function () {}
};

JSON.stringify(obj) // "{}"

如果数组的成员是undefined、函数或 XML 对象,则这些值被转成nullvar arr = [undefined, function () {}];
JSON.stringify(arr) // "[null,null]"
JSON.stringify(/foo/) // "{}"
JSON.stringify方法会忽略对象的不可遍历的属性。

第二个参数

JSON.stringify方法还可以接受一个数组,作为第二个参数,指定需要转成字符
串的属性。

var obj = {
  'prop1': 'value1',
  'prop2': 'value2',
  'prop3': 'value3'
};

var selectedProperties = ['prop1', 'prop2'];

JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"
上面代码中,JSON.stringify方法的第二个参数指定,只转
prop1和prop2两个属性。

这个类似白名单的数组,只对对象的属性有效,对数组无效。

第二个参数还可以是一个函数,用来更改JSON.stringify的返回值。

function f(key, value) {
  if (typeof value === "number") {
    value = 2 * value;
  }
  return value;
}

JSON.stringify({ a: 1, b: 2 }, f)
// '{"a": 2,"b": 4}'
上面代码中的f函数,接受两个参数,分别是被转换的对象的键名和键值。
如果键值是数值,就将它乘以2,否则就原样返回。

第三个参数

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 方法

如果参数对象有自定义的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":"张三"}"
上面代码中,JSON.stringify发现参数对象有toJSON方法,就直接使用这个方
法的返回值作为参数,而忽略原对象的其他参数。

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() **

JSON.parse方法用于将 JSON 字符串转换成对应的值。

JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('"foo"') // "foo"
JSON.parse('[1, 5, "false"]') // [1, 5, "false"]
JSON.parse('null') // null

var o = JSON.parse('{"name": "张三"}');
o.name // 张三

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}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值