详解Javascript中的Array对象
Posted 攻城狮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解Javascript中的Array对象相关的知识,希望对你有一定的参考价值。
基础介绍
创建数组
和Object对象一样,创建Array也有2种方式:构造函数、字面量法。
构造函数创建
使用构造函数的方式可以通过new关键字来声明,如下所示:
1
|
var arr = new Array();
|
当然也可以不通过new关键字来声明:
1
|
var arr = Array();
|
如果知道数组元素的个数,也可以直接传入数字表示元素个数:
1
|
var arr2 = new Array(5);
|
也可以直接传入数组元素:
1
|
var arr3 = new Array(5, "aa", "bb");
|
字面量法创建
通过字面量创建数组非常简单,推荐这种方式去创建数组:
1
|
var arr = [];
|
如果数组有一些初始值,可以直接写上去:
1
|
var arr2 = [5, "aa", "bb"];
|
数组长度
我们都知道要访问数组元素的个数很简单,直接通过length属性来获取到。
1
|
var arr = [2, 3, 4, 5];
|
但是和其他语言不同的是,在JS中,length属性是可以被设置的。
假设我们要清空一个数组,我们可以直接将length设置成0:
1
|
arr.length = 0;
|
可以看到,arr数组的元素被清空的
如果我们设置成负数会怎么样呢:
1
|
arr.length = -1;//Uncaught RangeError: Invalid array length
|
很明显,length是不允许被设置成负数的。
通过设置length属性,我们可以删除元素,比如:
1
|
var arr = [2, 3, 4, 5];
|
将length属性设置成比原来小的数值,后面的元素就会被移除掉。
如果将length设置成比原来大的数值会怎么样呢?
1
|
arr.length = 5;
|
可以看到,设置成比较大的数值后,多出来的元素值是undefined
数组检测
简单地介绍了Array之后,我们来说说如果检测一个变量是否是一个Array对象。这个也是一个比较常见的话题。
在ES5中,Array新增了一个检测数组对象的方法:Array.isArray。这个方法可以完美地确认一个对象是不是数组,无论这个对象是在哪个全局执行环境中创建的。
1
|
var arr = [2, 3, 4, 5];
|
对于不支持该方法的浏览器中,我们可以采用下面的polyfill:
1
|
if (!Array.isArray) {
|
一些常用的数组对象方法
Array对象中包含着很多有用的方法,尤其是在ES5,ES6中新增了许多方法,下面我们来总结一下。
静态方法
Array.from
Array.from是ES6种新增的方法,它可以将类数组对象或可迭代对象转换成数组对象。
常见的类数组对象比如有函数的arguments值,或者NodeList,htmlCollection对象等等。
常见的可迭代对象比如字符串,还有就是ES6新增的Set对象和Map对象。
我们来看看的基本用法,将一个arguments转换成数组对象:
1
|
var arr = (function () {
|
也可以将一个字符串转换成数组对象:
1
|
console.log(Array.from("abcdefg")); //["a", "b", "c", "d", "e", "f", "g"]
|
Array.from还包含2个可选参数:mapFn,thisArg
mapFn:将from返回的数组再进行处理再返回
thisArg:执行mapFn函数时this指向的值
假设页面上有多个span标签,我们想获取这些span标签里面的文本,这是html代码
1
|
<span>第一个span</span>
|
我们要获取span标签里面的文本成组成一个数组,可以这么做:
1
|
var spans = document.getElementsByTagName("span");
|
通过from函数将其转换成数组之后,再通过mapFn进行处理,获取每一个元素的innerText。
Array.from是ES6中新增的功能,必然有很多浏览器不支持,可以使用下面的polyfill:
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; var isArrayLike = function (collection) { var length = collection && collection.length; return typeof length == ‘number‘ && length >= 0 && length <= MAX_ARRAY_INDEX; }; var isFunction = function (fn) { return Object.prototype.toString.call(fn) === ‘[object Function]‘; } if (!Array.from) { Array.from = function (arrayLike, mapFn, thisArg) { if (!isArrayLike(arrayLike)) { throw new TypeError("被转换的对象不是一个类数组对象或可迭代对象"); } mapFn = isFunction(mapFn) ? mapFn : function (val, key) { return val; } var result = []; for (var i = 0, length = arrayLike.length; i < length; i++) { result.push(mapFn.call(thisArg, arrayLike[i], i)); } return result; } }
|
|
Array.isArray
Array.isArray是用来判断一个对象是否是数组,在前面判断数组类型的章节我们已经提到过了,这里就不再赘述啦。
Array.of
Array.of方法是ES6中新增的方法,它可以将传入的多个参数作为一个数组返回。看下面例子:
1
|
console.log(Array.of(2, 3, 4, 5)); //[2, 3, 4, 5]
|
通过传入4个参数,返回一个包含4个元素的数组。
注意Array.of与采用Array构造函数的区别,看下面代码:
1
|
console.log(Array(4));//[]
|
第一种方式采用Array构造函数的方式,创建了一个4个元素的数组,每个元素的值都是undefined。
第二中方式采用Array.of方法的方式,创建了一个1个元素的数组,元素值是4。
在不支持的浏览器中,可以采用下面的polyfill:
1
|
if (!Array.of) {
|
继承自Object的方法
我们知道,所有的引用类型都继承自Object对象,自然而然地包含了Object的一些方法。在Array中,我们主要说说其继承自Object的toString方法和valueOf方法。
toString方法
toString方法会返回对象的字符串表示,对于Array来说,这个方法会将每一个元素值用逗号分隔起来,最终形成一个字符串返回:
1
|
console.log([1, 2, 3, 4].toString()); //1,2,3,4
|
valueOf方法
valueOf方法用来返回对象的原始值,对于Array来说,它将返回数组本身:
1
|
console.log([1, 2, 3, 4].valueOf());//[1,2,3,4]
|
元素判断方法
在ES5中,Array原型中增加了2个判断数组是否满足某一条件的方法,下面分别来说明一下:
every方法
every方法用来判断数组中的所有元素是否都满足条件,如果全部满足则返回true,否则false。
every的用法如下:
1
|
arr.every(callback[, thisArg])
|
其中callback是用来判断每个元素是否满足条件的函数,它包含两个参数:元素值,索引,数组本身。
thisArg参数是可选的,它表示callback中this指向的对象。
看看下面的例子:
1
|
var arr = [1, 2, 3];
|
在不支持的浏览器中,可以采用下面的polyfill:
1
|
if (Array.prototype.every) {
|
some方法
some方法和every方法用法类似,但是它只需要数组中的某一个元素符合条件即返回true。
我们来看下面的例子:
1
|
var arr = [1, 2, 3];
|
在数组中,只有一项元素大于2,则返回true。
在不支持的浏览器中,可以采用下面的polyfill:
1
|
if (!Array.prototype.some) {
|
栈和队列方法
在js中,数组即可以像栈那个操作,也可以像队列那样操作,它提供了几个关于栈和队列的方法,这些方法相信大家非常熟悉,在这里简单地说明一下:
pop方法
pop方法会将数组的最后一个元素删除,然后返回这个被删除的元素
push方法
push方法是一个比较常用的方法,和pop方法相反,它用来将一个元素添加到元素的末尾,然后返回数组的长度。
shift方法
shift方法将第一个元素删除,然后返回这个元素
unshift方法
unshift在数组开头添加一个或多个元素,然后返回这个元素的长度:
1
|
var arr = [1, 2, 3];
|
元素索引方法
indexOf方法
indexOf方法用来返回元素在数组中的位置,不存在则返回-1:
1
|
var arr = [1, 2, 3];
|
indexOf方法有第二个可选参数,这个参数表示从哪个索引开始查找:
1
|
console.log(arr.indexOf(2, 1)); //1
|
如果这个参数大于数组长度,则直接返回-1,如果是负数,则将末尾进行抵消,然后开始查找,比如-1就从倒数第一开始查找,-2从倒数第二开始查找。
indexOf方法是ES5中提供的方法,对于不支持的浏览器,可以采用下面的polyfill:
1
|
if (!Array.prototype.indexOf) {
|
lastIndexOf方法
lastIndexOf方法和indexOf方法类似,它用于查找元素在数组最后一项的索引,如果不存在则返回-1:
1
|
var arr = [1, 5, 3, 4, 5, 6, 7];
|
如上面例子所示,数组中存在着两个数字5,使用indexOf方法将返回1,使用lastIndexOf将返回5。
lastIndexOf方法同样拥有第二个可选参数fromIndex,表示从该位置开始逆向查找。
如果fromIndex值大于或等于数组长度,则整个数组都会被查找。
如果fromIndex值为负值,并且其绝对值小于数组长度时,将从数组末尾向前查找。
如果fromIndex只为负数,但是其绝对值大于数组长度时,则直接返回-1。
1
|
var arr = [1, 5, 3, 4, 5, 6, 7];
|
对于不支持的浏览器,可以使用下面的polyfill:
if (!Array.prototype.lastIndexOf) { Array.prototype.lastIndexOf = function (element, fromIndex) { if (this.length === 0 || (fromIndex < 0 && this.length < Math.abs(fromIndex))) { return -1; } var length = this.length; var index = fromIndex || length - 1; if (fromIndex < 0) { index = length + fromIndex; } for (; index > -1; index--) { if (this[index] === element) { return index; } } return -1; } }
元素查找方法
findIndex方法
findIndex方法用来查找数组中符合条件的元素的索引,如果没有则返回-1。它包含两个参数:
callback:用来判断元素是否符合条件的回调函数,包含三个参数,分别是:当前元素,当前元素索引,数组
thisArg:可选参数,表示callback中this对象。
来看看下面的例子:
1
|
var arr = [1, 2, 3, 4, 5, 6];
|
查找第一个大于3的元素的索引,结果为3。
如果是一个比较复杂元素的数组,我们可以来查找其中符合某个条件的元素的索引:
1
|
var arr = [{ a: 1 }, { a: 2 }];
|
如果是要查找一个复杂对象,使用indexOf可能查找不到其索引,但是我们可以通过findIndex来找到其索引。这个对于查找复杂元素非常有用。
对于不支持的浏览器,可以使用下面的polyfill:
if (!Array.prototype.findIndex) { Array.prototype.findIndex = function (fn, thisArg) { if (!isFunction(fn)) { throw new TypeError("fn不是一个有效的函数"); } var arr = this; for (var i = 0, length = arr.length; i < length; i++) { if (fn.call(thisArg, arr[i], i, arr)) { return i; } } return -1; } }
find方法
find方法用户查找满足条件的第一个元素,如果没有满足条件的元素,则返回undefined。
find方法的用法和findIndex类似,它包含两个参数:
callback:用来判断元素是否符合条件的回调函数,包含三个参数,分别是:当前元素,当前元素索引,数组
thisArg:可选参数,表示callback中this对象。
来看看下面的例子:
1
|
var arr = [{ v: 1 }, { v: 3 }, { v: 4 }, { v: 5 }, { v: 6 }];
|
通过find方法,查找到第一个其属性v大于3的元素并返回。
大家在日常的开发中一定会遇到这种查找符合条件的元素的需求,find方法是一个非常有用的方法。
对于不支持的浏览器,可以采用下面的polyfill:
if (!Array.prototype.find) { Array.prototype.find = function (fn, thisArg) { if (!isFunction(fn)) { throw new TypeError("fn不是一个有效的函数"); } var arr = this; for (var i = 0, length = arr.length; i < length; i++) { if (fn.call(thisArg, arr[i], i, arr)) { return arr[i]; } } } }
元素排序方法
在Array对象中,它还包含了一些排序的方法,主要有sort和reverse两个方法,下面来说明一下这两个方法。
sort方法
sort方法用来对数组进行排序,并返回排序后的数组。它包含一个参数,这个参数是一个函数,用它来比较每个参数之前的前后关系。如果不传,则默认按照字符串的Unicode码位点进行排序。
看看下面的例子:
1
|
var arr = [2, 4, 6, 2, 4, 8, 11, 34];
|
如上结果所示,不指定比较函数的话,11排到了2前面,所以一般来说,我们要指定这个比较函数。
通过比较函数,我们可以来自定义数组排序的规则:
(1)返回-1,则元素a则排在了b前面
(2)返回0,位置不变
(3)返回1,元素a排在b后面
reverse方法
reverse方法是一个很简单的方法,它将数组元素的顺序进行倒序,并返回这个数组。
1
|
var arr = [1, 2, 3, 4, 5, 6, 7];
|
元素循环方法
Array对象中包含一些对元素进行遍历的方法,通过对元素进行遍历,从而进行不同的操作。
filter方法
filter方法是用来过滤数组的,通过传入一个回调函数,如果元素通过回调函数的测试,则保留该元素,否则丢弃。具体用法如下:
1
|
var arr = [2, 3, 4, 5, 6, 7, 8];
|
如上所示,通过回调函数,我们过滤掉那些值不大于3的元素。
对于回调函数,它包含3个参数:元素,元素索引,当前数组。
filter函数还包含一个可选的参数thisArg,它表示回调函数中this的指向。
对于不支持的浏览器,可以采用下面的polyfill:
if (!Array.prototype.filter) { Array.prototype.filter = function (fn, thisArg) { if (!isFunction(fn)) { throw new TypeError("fn不是一个有效的函数"); } var arr = this; var result = []; for (var i = 0, length = arr.length; i < length; i++) { if (fn.call(thisArg, arr[i], i, arr)) { result.push(arr[i]); } } return result; } }
forEach函数
forEach简单地说就是for循环的语法糖,它用于让数组的每一项都执行给定的函数。
看看下面的例子,循环数组的每一项,分别输入每一项。
1
|
var arr = [2, 3, 4, 5, 6, 7, 8];
|
和其他循环方法一样,forEach包含两个参数:
callback:循环每一项调用的函数,包含三个参数:元素,元素索引,当前数组
thisArg:可选的参数,表示callback中this的指向。
有一点要注意的是:除非是抛出异常,否则无法终止或跳出循环。
对于不支持的浏览器,可以采用下面的polyfill:
if (!Array.prototype.forEach) { Array.prototype.forEach = function (fn, thisArg) { if (!isFunction(fn)) { throw new TypeError("fn不是一个有效的函数"); } var arr = this; for (var i = 0, length = arr.length; i < length; i++) { fn.call(thisArg, arr[i], i, arr); } } }
reduce函数
reduct函数我们可以将其想象成一个累加器,从左到右依次将每个元素累加起来。
看看下面的例子:
1
|
var arr = [1, 2, 3, 4, 5];
|
这个例子中,通过reduce方法将数组的元素累加起来,计算总和。
reduct包含两个参数:
callback:累加调用函数,包含4个参数:
(1)上一次调用的返回值,默认情况下是第一个元素
(2)当前元素
(3)当前元素索引
(4)被循环的数组
initialValue:累加的初始值,不传则是第一个元素
对于不支持的浏览器,可以采用下面的polyfill:
if (Array.prototype.reduce) { Array.prototype.reduce = function (fn, initialValue) { if (!isFunction(fn)) { throw new TypeError("fn不是一个有效的函数"); } var arr = this; var result = initialValue || arr[0]; var index = !!initialValue ? -1 : 0; for (var length = arr.length - 1; index < length; index++) { result = fn(result, arr[index + 1], index + 1, arr); } return result; } }
reduceRight方法
reduceRight与reduce类似,只是从右向左开始调用回调函数,这里就不再赘述。
对于不支持的浏览器,可以使用下面的polyfill:
if (!Array.prototype.reduceRight) { Array.prototype.reduceRight = function (fn, initialValue) { if (!isFunction(fn)) { throw new TypeError("fn不是一个有效的函数"); } var arr = this; var result = initialValue || arr[arr.length - 1]; var index = !!initialValue ? arr.length : arr.length - 1; for (; index > 0; index--) { result = fn(result, arr[index - 1], index - 1, arr); } 以上是关于详解Javascript中的Array对象的主要内容,如果未能解决你的问题,请参考以下文章JavaScript原生对象属性和方法详解——Array对象