Array
Array可以包含任意数据类型,并通过索引来访问每个元素。直接给Array的length属性赋予一个新的值会导致Array大小的变化,其中未赋值的数据就是undefined. 因此不建议直接修改Array的大小,同时确保索引访问时不会出现索引越界。
属性
length
prototype
方法
Array.isArray()
Array.prototype.pop() 删掉最后一个元素
Array.prototype.push() 末尾添加若干元素
Array.prototype.reverse() 数组反转
Array.prototype.shift() 删掉第一个元素
Array.prototype.sort() 数组排序
Array的sort()方法默认是把所有元素都转换为String再排序
Array.prototype.splice() 从指定的索引开始删除若干元素然后再向该位置添加若干元素
Array.prototype.unshift() 头部添加若干元素
Array.prototype.concat() 将当前数组与指定数组连接起来返回新的数组
Array.prototype.join() 将数组每个元素都用指定的字符串连接起来返回字符串
Array.prototype.slice() 截取Array部分元素并返回一个新的Array,起止参数包括开始索引,不包括结束索引。如果不传递任何参数则从头到尾截取所有元素。
Array.prototype.toString()
Array.prototype.toLocaleString()
Array.prototype.indexOf() 搜索一个指定元素的位置
Array.prototype.lastIndexOf()
Array.prototype.forEach()
Array.prototype.every()
Array.prototype.some()
Array.prototype.filter()
用于过滤数组的某些元素然后返回剩下的元素
传入的函数依次作用于每个元素,然后根据返回值是true或者false来决定是否保留该元素,返回true则留下该元素
回调函数接收三个参数 function(element, index, self)
分别代表当前元素,当前元素索引,数组
//去除数组的重复元素 var r, arr=["apple","banana","pear","apple","orange","banana"]; r = arr.filter( function(element, index, self ){ return self.indexOf(element) === index; });
function getPrimes(arr){ return arr.filter(function(element){ if(element===1) return false; if(element===2) return true; for(var i=2; i<element; i++){ if(element%i===0){ return false; } } return true; }); }
Array.prototype.map()
function pow(x){ return x*x; } var arr = [1,2,3,4,5]; arr.map(pow);
map的经典大坑
var arr = ["1","2","3"]; var r = arr.map(parseInt); console.log(r);//[1,NaN,NaN]
Array.prototype.reduce()
var arr = [1,3,5,7,9]; arr.reduce(function(x,y){ return x+y; });
Array.prototype.reduceRight()
结合split, map, reduce组成一个string2Int()函数
function string2int(s){ return s.split("").map(function(x){ return x*1; }).reduce(function(x,y){ return x*10+y; }); }
// 在新生欢迎会上,你已经拿到了新同学的名单,请排序后显示 // 欢迎XXX,XXX,XXX和XXX同学! var arr = ['小明','小红','大军','阿黄']; alert('欢迎'+arr.sort().slice(0,arr.length-1).join(",")+'和'+arr[arr.length-1]+'同学!');
Array循环语句 for...in
循环得到的是String而不是Number
ES6对数组的扩展
1. Array.from()
用于将两类对象转换为真正的数组,这两类对象分别为: 类数组对象 和 可遍历对象
类数组对象 是指 拥有Length属性和若干索引属性的对象
可遍历对象 是值 实现了iterable接口的对象,如Map Set String Array
let arrayLike = { "0": "a", "1": "b", "2": "c" } Array.from(arrayLike);
在ES5中,需要使用 [].slice()方法,将这个方法通过call()运用到类数组对象上。实际生产中,常用的类数组对象包括DOM操作返回的NodeList对象,函数内部的arguments对象
在ES6中,扩展运算符(...)俗称三个点,可以将某些数据结构解析为数组。但是三个点不能用于类数组对象,因为扩展运算符的工作原理是调用遍历器接口来转换成数组
Array.from()方法还可以接收第二个参数和第三个参数
Array.from()的第二个参数mapFn 是一个函数,作用在于对每个元素进行最后一次处理,然后将处理后的值放入新的数组中
// 将数组中未定义的值转换为0 Array.from([1,2, , 0, , 3], x=>x||0); // 将类数组对象也进行转换 Array.from({length: 3}, x=>x||0); // 返回函数调用时传入的所有参数的类型 function getTypes(){ return Array.from(arguments, arg => typeof arg); }
最后一个常用场景是 将字符串转换为数组然后返回字符串的长度
第三个参数是用来绑定map函数中的this对象
2. Array.of()
这个方法的目的是弥补Array()构造函数传入参数不同时产生不同效果的先天不足
Array(4) ==> [, , , ,] 得到的是一个长度为4的空数组
Array() ==> []
Array(1,2) =>[1, 2]
我想创建单个元素的数组怎么办? 在ES5中实现: var a = new Array(); a[0]=5;
于是在ES6中实现: Array.of(5) 得到的就是具有单一元素5的数组
Array.of(); // [] Array.of([]); //[ [] ] Array.of(5); // [5] Array.of(undefined); // [undefined] Array.of([1,2]); // [1,2]
同理在ES5中也可以依靠 [].slice.call(arguments) 来模拟 Array.of()方法
3. copyWithin()
浅赋值数组的一部分到同一数组的其他位置,并返回新数组,而不修改其大小
(在当前数组内部将指定位置的成员复制到其他位置会覆盖原有成员,然后返回当前数组)
Array.prototype.copyWithin(target, start = 0, end = this.length)
三个参数
target 从该位置开始替换数据
start 从该位置开始读取数组 默认为0 负数表示倒着开始数数
end 到该位置前停止读取数据,也就是说不包含这个位置的数据。默认为length 负数表示倒着数数
// 将索引3号位置的值复制到索引0号位置 [1,2,3,4,5].copyWithin(0, 3, 4); // ==> [4,2,3,4,5] [1,2,3,4,5].copyWithin(0,-2,-1); // ==> [4,2,3,4,5] [].copyWithin.call({length:3, "3":1}, 0, 3); // ==> {length: 3, "0":1, "3":1}
4. find() findIndex()
find() 用来找出第一个符合条件的数组成员
arr.find(callback, [thisArg]);
数组中的每个成员依次执行回调函数,直到找出第一个返回值为true的数组成员并将其返回。如果没有找到符合条件的成员则返回undefined
// 找出第一个负数 [1,4,-5,10,-10].find(x=>x<0); // 回调函数也接收三个参数 // 所有数组方法中的回调函数的参数基本上都是一个套路 // 当前元素,当前索引,数组本身 [1,5,10,15].find((element, index, arr)=> element>9 );
findIndex() 返回第一个符合条件的数组成员的索引位置
arr.findIndex(callback, [thisArg]);
如果没有找到符合条件的成员,那么返回 -1
这两个方法可以弥补IndexOf()无法判断NaN的缺陷,因为NaN 和 NaN 是不相等的
5. fill()
用一个固定值来填充一个数组中从起始索引到终止索引(不包含终止索引)内的全部元素
Array.prototype.fill(value, start, end);
由于已经存在的元素会被抹去,所以经常用于空数组的初始化,比如创建一个数组元素都一样的指定长度的数组
new Array(7).fill(5); 得到 [5,5,5,5,5,5,5] 长度为7,数组元素全部为5
第二个参数表示起始索引,默认值 = 0,第三个参数表示终止索引,默认值 = this.length。牢记不要填充终止索引。将修改后的数组进行返回,而不会改变原来的数组。
['a', 'b', 'c'].fill(7, 1, 2); // == > ['a', 7, 'c']
6. entries() keys() values()
在ES6中提供了三种遍历数据结构的方法 entries() keys() values() 这三个方法都会返回一个遍历器对象,所以都支持for ... of 循环
区别在于遍历的对象不同,entries()遍历的是键值对, keys() 遍历的是键名, values() 遍历的是键值
(放在ES6数据结构Iterator遍历一节中专门讨论)
7. includes()
用来判断数组中是否包含给定的值
Array.prototype.includes(searchElement, fromIndex = 0) 返回一个布尔值
第二个参数表示开始搜索的起始位置,默认为0,如果为负数表示倒着开始数数
这个方法未来会是一个通用且重要的方法,相比较于indexOf()方法,该方法的优点在于语义清晰,且可以用来判断NaN。
对于不支持该方法的浏览器,可以使用polyfill方案
8. ES6明确规定数组中的空值都会被转换为undefined进行处理
建议数组中不要出现空值,那怕就是给个null或者undefined都强很多
9. 数组推导
数组推导,允许直接通过现有数组生成新的数组。完整功能放在了ES7中,目的是支持所有的实现了Iterator接口的数据结构。
功能类似于Python的列表生成式。如果大家了解Python就会发现和列表生成式的语法很相似。
未来数组推导功能肯定会取代map , filter这种过滤方法