Array对象
Array
是 JavaScript 的原生对象,同时也是一个构造函数,可以用它生成新的数组。Array
构造函数有一个很大的缺陷,就是不同的参数,会导致它的行为不一致。所以不推荐用构造函数来生成新数组,而是直接使用数组字面量来生成新数组。
var arr = new Array(2);
arr // [ empty x 2 ];
// 无参数时,返回一个空数组
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']
//字面量方式
var arr = [1, 2];
Array的静态方法和实例方法
-
Array.isArray()
方法返回一个布尔值,表示参数是否为数组。它可以弥补typeof
运算符的不足。(静态方法) -
valueOf()
方法是一个所有对象都拥有的方法,表示对该对象求值。不同对象的valueOf()
方法不尽一致,数组的valueOf()
方法返回数组本身。 -
toString()
方法也是对象的通用方法,数组的toString
方法返回数组的字符串形式。 -
push()
方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。 -
pop()
方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。push()
和pop()
结合使用,就构成了“后进先出”的栈结构(stack)。 -
unshift()
方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。 -
shift()
方法用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。push()
和shift()
结合使用,就构成了“先进先出”的队列结构(queue)。 -
join()
方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回,如果不提供参数,默认用逗号分隔,原数组不变。通过call
方法,这个方法也可以用于字符串或类似数组的对象。 -
concat()
方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。如果数组成员包括对象,concat
方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。 -
reverse()
方法用于颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组。 -
slice()
方法用于提取目标数组的一部分,返回一个新数组,原数组不变。它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原数组的最后一个成员。如果参数是负数,则表示倒数计算的位置。如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。slice
方法的一个重要应用,是将类似数组的对象转为真正的数组。 -
splice()
方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。splice
的第一个参数是删除的起始位置(从0开始),第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。起始位置如果是负数,就表示从倒数位置开始删除。如果只是单纯地插入元素,splice
方法的第二个参数可以设为0
。如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。 -
sort()
方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。如果想让sort
方法按照自定义方式排序,可以传入一个函数作为参数。sort
的参数函数本身接受两个参数,表示进行比较的两个数组成员。如果该函数的返回值大于0,表示第一个成员排在第二个成员后面;其他情况下,都是第一个元素排在第二个元素前面。 -
map()
方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回,改变原数组。map
方法接受一个函数作为参数。该函数调用时,map
方法向它传入三个参数:当前成员、当前位置和数组本身。如果数组有空位,map
方法的回调函数在这个位置不会执行,会跳过数组的空位,不会跳过undefined
和null
。map
方法还可以接受第二个参数,用来绑定回调函数内部的this
变量,下面代码通过map
方法的第二个参数,将回调函数内部的this
对象,指向arr
数组。
var arr = ['a', 'b', 'c'];
[1, 2].map(function (e) {
return this[e];
}, arr)
// ['b', 'c']
-
forEach()
方法与map
方法很相似,也是对数组的所有成员依次执行参数函数,将会改变原数组。但是,forEach
方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用map
方法,否则使用forEach
方法。forEach
的用法与map
方法一致,参数用法和跳过空位都一致。 -
filter()
方法用于过滤数组成员,满足条件的成员组成一个新数组返回。它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。filter
方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。filter
方法还可以接受第二个参数,用来绑定参数函数内部的this
变量。
[1, 2, 3, 4, 5].filter(function (elem) {
return (elem > 3);
})
// [4, 5] 满足大于3的数组成员,作为一个新数组返回。
var arr = [0, 1, 'a', false];
arr.filter(Boolean)
// [1, "a"] 返回数组arr里面所有布尔值为true的成员
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]
//过滤器myFilter内部有this变量,它可以被filter方法的第二个参数obj绑定,返回大于3的成员
-
some()
,every()
这两个方法类似“断言”(assert),返回一个布尔值,表示判断数组成员是否符合某种条件。它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。-
some
方法是只要一个成员的返回值是true
,则整个some
方法的返回值就是true
,否则返回false
。 -
every
方法是所有成员的返回值都是true
,整个every
方法才返回true
,否则返回false
。 - 注意,对于空数组,
some
方法返回false
,every
方法返回true
,回调函数都不会执行。
-
-
reduce()
,reduceRight()
方法依次处理数组的每个成员,最终累计为一个值。它们的差别是,reduce
是从左到右处理(从第一个成员到最后一个成员),reduceRight
则是从右到左(从最后一个成员到第一个成员),其他完全一样。reduce
方法和reduceRight
方法的第一个参数都是一个函数,该函数接受四个参数:1、累积变量,默认为数组的第一个成员,2、当前变量,默认为数组的第二个成员,3、当前位置(从0开始),4、原数组。这四个参数之中,只有前两个是必须的,后两个则是可选的。
[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方法的第二个参数。处理空数组很有用
[1, 2, 3, 4, 5].reduce(function (a, b) {
return a + b;
}, 10);
// 25 指定参数a的初值为10,所以数组从10开始累加,最终结果为25。注意,这时b是从数组的第一个成员开始遍历。
处理空数组
function add(prev, cur) {
return prev + cur;
}
[].reduce(add)
// TypeError: Reduce of empty array with no initial value
[].reduce(add, 1)
// 1 由于空数组取不到初始值,reduce方法会报错。这时,加上第二个参数,就能保证总是会返回一个值。
由于这两个方法会遍历数组,所以实际上还可以用来做一些遍历相关的操作。比如,找出字符长度最长的数组成员。
function findLongest(entries) {
return entries.reduce(function (longest, entry) {
return entry.length > longest.length ? entry : longest;
}, '');
}
findLongest(['aaa', 'bb', 'c']) // "aaa"
-
indexOf()
方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1
,还可以接受第二个参数,表示搜索的开始位置。 -
lastIndexOf()
方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1,indexOf,lastIndexOf
这两个方法不能用来搜索NaN的位置,即它们无法确定数组成员是否包含NaN
,这是因为这两个方法内部,使用严格相等运算符(===
)进行比较,而NaN
是唯一一个不等于自身的值。
上面这些数组方法之中,有不少返回的还是数组,所以可以链式使用。
//上面代码中,先产生一个所有 Email 地址组成的数组,然后再过滤出以t开头的 Email 地址,最后将它打印出来。
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
三个原生对象。这三个原生对象可以把原始类型的值变成(包装成)对象。包装对象的最大目的,首先是使得 JavaScript 的对象涵盖所有的值,其次使得原始类型的值可以方便地调用某些方法。Number
、String
和Boolean
如果不作为构造函数调用(即调用时不加new
),常常用于将任意类型的值转为数值、字符串和布尔值。
//生成包装对象
var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);
三种包装对象各自提供了许多实例方法,它们共同具有、从Object
对象继承的方法:valueOf
和toString
。valueOf
方法返回包装对象实例对应的原始类型的值。toString
方法返回对应的字符串形式。
原始类型的值,可以自动当作包装对象调用,即调用包装对象的属性和方法。这时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,在使用后立刻销毁实例。假如abc
是一个字符串,本身不是对象,不能调用length
属性。JavaScript 引擎自动将其转为包装对象,在这个对象上调用length
属性。调用结束后,这个临时对象就会被销毁。这就叫原始类型与实例对象的自动转换。自动转换生成的包装对象是只读的,无法修改。所以,字符串无法添加新属性。除了原生的实例方法,包装对象还可以自定义方法和属性,供原始类型的值直接调用。
注意:调用结束后,包装对象实例会自动销毁。这意味着,下一次调用字符串的属性时,实际是调用一个新生成的对象,而不是上一次调用时生成的那个对象,所以取不到赋值在上一个对象的属性。如果要为字符串添加属性,只有在它的原型对象
String.prototype
上定义。
Boolean对象
Boolean
对象是 JavaScript 的三个包装对象之一。作为构造函数,它主要用于生成布尔值的包装对象实例。注意,false
对应的包装对象实例,布尔运算结果也是true
。Boolean
对象除了可以作为构造函数,还可以单独使用,将任意值转为布尔值。这时Boolean
就是一个单纯的工具方法。使用双重的否运算符(!
)也可以将任意值转为对应的布尔值。
Number对象
Number
对象是数值对应的包装对象,可以作为构造函数使用,也可以作为工具函数使用。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
。
Number
对象有4个实例方法,都跟将数值转换成指定格式有关。
-
Number
对象部署了自己的toString
方法,用来将一个数值转为字符串形式。此方法只能将十进制的数,转为其他进制的字符串。如果要将其他进制的数,转回十进制,需要使用parseInt
方法。
//toString方法可以接受一个参数,表示输出的进制。
//如果省略这个参数,默认将数值先转为十进制,再输出字符串;否则,就根据参数指定的进制,将一个数字转化成某个进制的字符串。
(10).toString() // "10"
//10一定要放在括号里,这样表明后面的点表示调用对象属性。如果不加括号,这个点会被 JavaScript 引擎解释成小数点,从而报错。
10.toString(2) // SyntaxError: Unexpected token ILLEGAL
//通过方括号运算符也可以调用toString方法。
10['toString'](2) // "1010"
-
toFixed
方法先将一个数转为指定位数的小数,然后返回这个小数对应的字符串。参数为小数位数,有效范围为0到20,超出这个范围将抛出 RangeError 错误。 -
toExponential
方法用于将一个数转为科学计数法形式。参数是小数点后有效数字的位数,范围为0到20,超出这个范围,会抛出一个 RangeError 错误。 -
toPrecision
方法用于将一个数转为指定位数的有效数字。参数为有效数字的位数,范围是1到21,超出这个范围会抛出 RangeError 错误。 - 与其他对象一样,
Number.prototype
对象上面可以自定义方法,被Number
的实例继承。
String对象
String
对象是 JavaScript 原生提供的三个包装对象之一,用来生成字符串对象。字符串对象是一个类似数组的对象(很像数组,但不是数组)。除了用作构造函数,String
对象还可以当作工具方法使用,将任意类型的值转为字符串。
String的静态方法和实例方法
-
String.fromCharCode()
静态方法(即定义在对象本身,而不是定义在对象实例的方法),该方法的参数是一个或多个数值,代表 Unicode 码点,返回值是这些码点组成的字符串。注意,该方法不支持 Unicode 码点大于0xFFFF
的字符,即传入的参数不能大于0xFFFF
(即十进制的 65535)。这种现象的根本原因在于,码点大于0xFFFF
的字符占用四个字节,而 JavaScript 默认支持两个字节的字符。这种情况下,必须把0x20BB7
拆成两个字符表示。 - 字符串实例的
length
属性返回字符串的长度。 -
charAt()
方法返回指定位置的字符,参数是从0开始编号的位置。如果参数为负数,或大于等于字符串的长度,charAt
返回空字符串。 -
charCodeAt()
方法返回字符串指定位置的 Unicode 码点(十进制表示),相当于String.fromCharCode()
的逆操作。参数是字符串的下标,如果没有任何参数,charCodeAt
返回首字符的Unicode
码点。如果参数为负数,或大于等于字符串的长度,charCodeAt
返回NaN
。注意,charCodeAt
方法返回的 Unicode 码点不会大于65536(0xFFFF),也就是说,只返回两个字节的字符的码点。如果遇到码点大于 65536 的字符(四个字节的字符),必需连续使用两次charCodeAt
,不仅读入charCodeAt(i)
,还要读入charCodeAt(i+1)
,将两个值放在一起,才能得到准确的字符。 -
concat()
方法用于连接两个字符串,返回一个新字符串,不改变原字符串。 -
slice()
方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。如果省略第二个参数,则表示子字符串一直到原字符串结束。如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度。如果第一个参数大于第二个参数,slice
方法返回一个空字符串。 - substring方法用于从原字符串取出子字符串并返回,不改变原字符串,跟
slice
方法很相像。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置(返回结果不含该位置)。如果省略第二个参数,则表示子字符串一直到原字符串的结束。如果第一个参数大于第二个参数,substring
方法会自动更换两个参数的位置。如果参数是负数,substring
方法会自动将负数转为0。由于这些规则违反直觉,因此不建议使用substring
方法,应该优先使用slice
。 -
substr()
方法用于从原字符串取出子字符串并返回,不改变原字符串,跟slice
和substring
方法的作用相同。第一个参数是子字符串的开始位置(从0开始计算),第二个参数是子字符串的长度。如果省略第二个参数,则表示子字符串一直到原字符串的结束。如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,将被自动转为0,因此会返回空字符串。 -
indexOf()
方法用于确定一个字符串在另一个字符串中第一次出现的位置,返回结果是匹配开始的位置。如果返回-1
,就表示不匹配。可以接受第二个参数,表示从该位置开始向后匹配。 -
lastIndexOf()
方法的用法跟indexOf
方法一致,主要的区别是lastIndexOf
从尾部开始匹配,indexOf
则是从头部开始匹配。第二个参数表示从该位置起向前匹配。 -
trim()
方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。该方法去除的不仅是空格,还包括制表符(\t
、\v
)、换行符(\n
)和回车符(\r
)。 -
toLowerCase
方法用于将一个字符串全部转为小写,toUpperCase
则是全部转为大写。它们都返回一个新字符串,不改变原字符串。 -
match()
方法用于确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。如果没有找到匹配,则返回null。适用于正则 -
search()
方法的用法基本等同于match,但是返回值为匹配的第一个位置。如果没有找到匹配,则返回-1
。适用于正则 -
replace()
方法用于替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式)。适用于正则 -
split()
方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。适用于正则
如果分割规则为空字符串,则返回数组的成员是原字符串的每一个字符。
'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"]
'a|b|c'.split('|', 3) // ["a", "b", "c"]
'a|b|c'.split('|', 4) // ["a", "b", "c"]
-
localeCompare()
方法用于比较两个字符串。它返回一个整数,如果小于0,表示第一个字符串小于第二个字符串;如果等于0,表示两者相等;如果大于0,表示第一个字符串大于第二个字符串。
Math对象
Math
是 JavaScript 的原生对象,提供各种数学功能。该对象不是构造函数,不能生成实例,所有的属性和方法都必须在Math对象上调用。
Math的静态属性
-
Math.E
:常数e。 -
Math.LN2
:2 的自然对数。 -
Math.LN10
:10 的自然对数。 -
Math.LOG2E
:以 2 为底的e的对数。 -
Math.LOG10E
:以 10 为底的e的对数。 -
Math.PI
:常数π。 -
Math.SQRT1_2
:0.5 的平方根。 -
Math.SQRT2
:2 的平方根。
Math的静态方法
-
Math.abs()
:绝对值,返回参数值的绝对值。 -
Math.ceil()
:向上取整,返回大于参数值的最小整数(天花板值)。 -
Math.floor()
:向下取整,返回小于参数值的最大整数(地板值)。 -
Math.max()
:最大值,返回参数之中最大的那个值 -
Math.min()
:最小值,返回参数之中最小的那个值 -
Math.pow()
:指数运算,返回以第一个参数为底数、第二个参数为幂的指数值。 -
Math.sqrt()
:平方根,返回参数值的平方根。如果参数是一个负值,则返回NaN
。 -
Math.log()
:自然对数,返回以e
为底的自然对数值。 -
Math.exp()
:e的指数,返回常数e的参数次方。 -
Math.round()
:四舍五入 -
Math.random()
:随机数,返回0到1之间的一个伪随机数,可能等于0,但是一定小于1。
Math对象的三角函数方法
-
Math.sin()
:返回参数的正弦(参数为弧度值) -
Math.cos()
:返回参数的余弦(参数为弧度值) -
Math.tan()
:返回参数的正切(参数为弧度值) -
Math.asin()
:返回参数的反正弦(返回值为弧度值) -
Math.acos()
:返回参数的反余弦(返回值为弧度值) -
Math.atan()
:返回参数的反正切(返回值为弧度值)