一、数组遍历
Array提供了5种遍历操作数组元素的方法,有map、forEach、filter、some、every,他们分别适用于不同的场合,下面一一解析。
1. map方法
map方法接受两个参数,第一个参数是函数,第二个参数可以用来绑定函数执行中的this。map会把每个元素作为参数传入函数,然后将每个函数结果组成新数组返回。会跳过空位,不会跳过null和undefined。
2. forEach方法
forEach方法接受两个参数,第一个参数是函数,第二个参数指定函数执行中的this指向。forEach会把每个元素作为参数传入函数进行处理(仅处理,不会有返回结果)。且无法用break
和continue
中断执行,若要中断请用for。
3. filter方法
filter同样接受两个参数,把每个元素作为函数参数传入,将函数结果为true的元素组成的新数组。
4. some方法
some也接受两个参数,把每个元素作为函数参数传入,只要函数结果有一个返回true则some返回true。对于空数组some返回false,且回调函数不执行。
5. every方法
every也接受两个参数,把每个元素作为函数参数传入,所有函数结果都返回true时则every返回true。对于空数组every返回true,且回调函数不执行。
总结补充:
- 除了forEach没返回值,其他4个都有返回值,some和every返回的是布尔值,map和filter返回的是数组。由于filter和map返回的都是数组,可以链式调用,即map的结果可以再调用map。
- 上面的是Array提供的遍历方法,而可以用来遍历数组还有
for
和for-of
和for-in
。其中for-of
是es6增加的用来遍历具有iterator接口的数据结构的值的,而数组原生具备iterator接口,所以可用来遍历数组。for-in
是用来遍历对象属性的,而数组也是对象的一种(但不推荐用此法遍历数组,因为for-in
会遍历所有可枚举属性包括继承的)。用法如下:
var arr = ['first', 'second', 'third'];
// for用法
for (var i=0,len=arr.length; i<len; i++) { // 先将len存起来以免动态增加或多次重复读取len
console.log(arr[i]);
}
// for-of用法
for (var value of arr) {
console.log(value);
}
// for-in用法
for (var key in arr) {
console.log(arr[key]);
}
// 上面三种都依次打印出 first second third
- 遍历效率:for > for-of > forEach > map > for-in
二、数组的截取
slice用于截取某个区域段的元素,然后返回这些元素组成的新数组,原数组不发生改变。该方法接受两个参数,第一个参数表示从数组哪个位置(包含)开始截取,第二个表示到哪个位置(不包含)停止截取,若没有第二个参数则默认为arr.length。两个参数若为负数则倒着算,如果第一个参数大于第二个则返回空数组。
var arr = [1, 2, 3, 4];
arr.slice(1); // [2, 3, 4],相当于arr.slice(1, arr.length)
arr.slice(1, 3); // [2, 3]
arr.slice(-4, -1); // [1, 2, 3],相当于arr.slice(arr.length-4, arr.length-1)
arr.slice(3, 2); // []
slice还有一个作用,可以用来将类数组对象转换为真正的数组。详细见下文。
三、数组判断
判断某个变量是否某种类型我们一般用typeof
,但是typeof
返回的只有基本数据类型(number, string, boolean, undefined, null, object, symbol
;在此基础上去掉了null
增加了function
)。而Array也是一种对象,所以返回的也是object
,并不会返回array
,如下:
typeof 1; // "number"
typeof 'hello'; // "string"
typeof true; // "boolean"
typeof Symbol(); // "symbol",es6新增数据类型
typeof undefined; // "undefined"
typeof null; // "object"
typeof function(){}; // "function"
typeof new Object(); // "object"
typeof new Array(); // "object"
所以使用typeof来判断一个变量是否为数组并不可行。若要判断是否为数组,主要有以下四种方法:
1. 通过instanceof判断
instanceof
主要用来判断某对象是否为另一个对象的实例的,而所有数组都是Array的实例,所以可以用此法判断变量是否为数组。instanceof
的主要实现原理是判断某构造函数的prototype
是否在被检测对象的原型链上。用法如下:
var arr = [1, 2];
arr instanceof Array; // true
2. 通过constructor判断
由于所有数组都是Array的实例,而实例的constructor
会返回对应的构造函数,所以所有数组的constructor
都是Array
,可以通过此法来判断是否为数组。
var arr = [1, 2];
arr.constructor === Array; // true
3. 通用Object.prototype.toString()判断
Object.prototype.toString()
会返回对象的字符串形式,如[object Object]
,该字符串第一个是typeof
的值,第二个是constructor
的值,所以数组返回的是[object Array]
。由于基本所有实例的原型链上都有Object.prototype,所以数组实例可以调用借用此法然后判断返回值是否是[object Array]
来判断是不是数组。
var arr = [];
Object.prototype.toString.apply(arr) === '[object Array]'; // true
4. 通过Array.isArray()判断
ES6新增了一个Array.isArray()
专门用于判断数组,这样的写法比上面几种更简洁明了表明了意图,使用起来也非常方便。
var arr = [];
Array.isArray(arr); // true
四、数组转化
有时候,我们会有一些类似数组的但实际又不是数组的对象,我们称为类数组对象,如string
、DOM节点的NodeList
、方法参数arguments
等,他们一般都有数字作为索引且有length
属性。由于他们不是真正的数组,所以无法使用数组的push
等方法,要想使用需要先转为真正的数组(虽然可以call
借用数组方法但效率没比处理真正的数组高)。一般有如下三种方法:
1. 通过slice来转化
var str = 'hello';
Array.prototype.slice.call(str); // ["h", "e", "l", "l", "o"]
Array.prototype.slice.apply(str); // ["h", "e", "l", "l", "o"]
Array.prototype.slice.bind(str)(); // ["h", "e", "l", "l", "o"]
2. Array.from()
ES6提供了真正转数组的方法Array.from()
,他可以用来将类数组对象和具有Iterator接口的对象转为真正的数组,用法如下:
var str = 'hello';
Array.from(str); // ["h", "e", "l", "l", "o"]
3. 扩展运算符
ES6的扩展运算符...
能将具有Iterator接口的对象展开成多个序列元素。
var str = 'hello';
[...str]; // // ["h", "e", "l", "l", "o"]
五、创建数组
创建数组主要有3种方法,但也还可以借用转换成数组的方法生成数组:
1. 字面量法
var = [1, 2, 3]; // 最直接也最容易的方法
2. new构造函数法
用Array构造函数来生成数组实例,可以接受多个参数作为数组元素,当只有一个参数是表示数组长度。
var arr1 = new Array(1, 2, 3); // [1, 2, 3]
var arr2 = new Array(3); // [empty × 3] 即 [ , , ]
var arr3 = new Array('3'); // ["3"]
3. Array.of()
可以看到,上面的new构造法当只传一个数值元素的时候,会把他当做数组的长度,这样就没法生成一个只有一个数值元素的数组了,所以ES6有了Array.of()
来统一都把参数都当做元素。
var arr1 = Array.of(1, 2, 3); // [1, 2, 3]
var arr2 = Array.of(3); // [3]
var arr3 = Array.of('3'); // ["3"]
4. 转数组法
如果想指定生成多少个元素的数组,还可以借助Array.from()
、Array.apply()
等转换数组的方法,可以创造如下只有长度的类数组对象。
Array.from({length: 3}); // [undefined, undefined, undefined]
Array.apply(null, {length: 3}); // [undefined, undefined, undefined]
[...Array(3)]; // [undefined, undefined, undefined]