最近在学习Javascript数组的内容,因为数组在编程中非常常用,是一个很重要的知识点,JS中的数组也和之前学习过的JAVA中的数组有一定的区别,所以写下了这篇博客,用来记录JS数组相关的知识,便于自己查阅和复习。
JS数组和典型数组的区别
典型数组
- 元素数据类型相同
- 使用连续的内存存储
- 通过数字下标获取元素
JS数组
- 元素数据类型可以不同
- 内存不一定连续(随机存储)
- 不能通过数字下标(因为JS的对象没有数字下标),而是通过字符串下标
- 这就意味着数组可以有任何的key
let arr = [1,2,3]
arr['xxx'] = 1
为什么一开始数组有三个元素分别为1,2,3,length为3,后来又添加了一个下标为'xxx'字符串,值为4的元素,length还是3呢?
MDN上是这样描述的:
如果你在以上代码中给数组操作符的是一个非整形数值,那么将作为一个代表数组的对象的属性(property)创建,而非作为数组的元素。
var arr = [];
arr[3.4] = "Oranges";
console.log(arr.length); // 0
console.log(arr.hasOwnProperty(3.4)); // true
所以当我们试图为JavaScript的数组添加非整形数值字符串下标的时候,其实相当于为该数组对象添加了一个自有属性property,而不是增加了一个数组元素。由于数组对象添加属性不会影响到length的值,所以length并没有发生变化。同样的数组的pop和shift等方法也不能作用于这些属性身上。
另外,当我们给数组添加整型数组字符串下标时,会把字符串转换成整型数字作为下标。
我们想像添加非整型数值字符串一样把'101'当成数组的自有属性存储,结果整型字符串'101'却被强行转换成整型数字,当作数组元素存放了。
创建数组
新建
- let arr=[1,2,3] //简单写法
- let arr=new Array(1,2,3) //标准写法
- let arr=new Array(3) //长度为3的空数组,而不是长度为1,值为3的数组
转化
- let arr='1,2,3'.split(',') //以','为分隔符将字符串转化为数组
- let arr='123'.split('') //以空字符为分隔符将字符串转化为数组
- Array.from('123') //将一个类数组对象或者可遍历对象转换成一个真正的数组
合并
- arr1.concat(arr2) //合并两个数组得到新数组
截取
截取一个数组的一部分得到一个新数组
- arr1.slice(1) //从第二个元素开始
- arr2.slice(0) //全部截取
伪数组
let divList=document.querySelectorAll('div')
伪数组有数组的length属性,原型链中却没有数组的原型
数组元素的删除
delete
delete arr['0']只删除下标0对应的值,置为empty,下标0依然存在,数组的length不变。如果数组中的数值全部用delete删除,则变成稀疏数组。
length
直接设置arr.length值可以把数组截断,只保留前${length}个元素,但不建议这样使用。
shift
删除头部的元素,并返回被删除的元素。
arr.shift()
pop
删除尾部的元素,并返回被删除的元素。
arr.pop()
splice
可以实现删除元素,添加元素或者替换元素。
arr.splice(index,1) //index为开始删除的下标,后面的数字为想删除的个数
arr.splice(index,1,'x') //在删除的地方添加'x',相当于把这个元素替换成了'x'
arr.splice(index,1,'x','y') //在index下标开始删除一个元素并添加'x'和'y'
arr.splice(2) //从下标为2的地方开始删除后面所有元素
arr.splice(2,0,'x') //从下标为2的地方开始删除0个元素,增加一个'x'元素,这个元素加在下标2的前面
arr.splice(-2,1) //从数组索引最末端开始往前数的第二个下标开始删除1个元素
查看所有元素
查看所有属性名
let arr=[1,2,3,4,5]
arr.x='xxx'
Object.keys(arr)
for(let key in arr){
console.log(`${key}:${arr[key]}`)
} //这是遍历对象属性的方法,如果是要遍历数组则不是很建议使用,如果数组里有property,会输出property的值,和预期结果不符
查看数字(字符串)属性名和值
for(let i==0;i<arr.length;i++){
console.log(`${i}:${arr[i]}`)
}//可以提前break
arr.forEach(function(item,index){
console.log(`${index}:${item}`)
})//不能break
手写Array.forEach()
function forEach(array,fn){
for(let i=0;i<array.length;i++){
fn(array[i],i,array)
}
}
查看单个属性
查找某个元素是否在数组里
arr.indexOf(item) 存在返回索引,不存在返回-1。
使用条件查找元素
arr.find(item=>item%2===0)找第一个偶数。
使用条件查找元素的索引
arr.findIndex(item=>item%2===0)
增加数组中的元素
在尾部加元素
arr.push(newItem)
arr.push(item1,item2)
在头部加元素
arr.unshift(newItem)
arr.unshift(item1,item2)
在中间添加元素
arr.splice(index,0,'x')
arr.splice(index,0,'x','y')
修改数组中的元素
反转顺序
arr.reverse()
例:var a=[1,2,3,4,5]
a.reverse()
console.log(a) //[5,4,3,2,1]
自定义顺序
arr.sort([compareFunction(first,second)])
compareFunction是用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行升序排序(给数组[3,2,1,4,10]排序会变成[1,10,2,3,4],10的unicode码比2小),返回值是原数组,不生成新的数组。
如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:
- 如果
compareFunction(a, b)小于 0 ,那么 a 会被排列到 b 之前; - 如果
compareFunction(a, b)等于 0 , a 和 b 的相对位置不变。 - 如果
compareFunction(a, b)大于 0 , b 会被排列到 a 之前。
function compare(a, b) {
if (a < b ) { // 升序排序
return -1;
}
if (a > b ) {
return 1;
}
// a must be equal to b
return 0;
}
---------------------------------------------------
function compare(a, b) {
if (a < b ) { // 降序排序
return 1;
}
if (a > b ) {
return -1;
}
// a must be equal to b
return 0;
}
数组变换
map(n变n)
map 方法会迭代数组中的每一个元素,并根据回调函数来处理每一个元素,最后返回一个新数组。注意,这个方法不会改变原始数组。
var oldArray= [1,2,3,4,5]
var newArray = oldArray.map(function(data){
return data+3
})//数组每个元素加三
filter(n变少)
filter方法用来迭代一个数组,并且按给出的条件过滤出符合的元素。filter 方法传入一个回调函数,这个回调函数会携带一个参数,参数为当前迭代的项(我们叫它 val )。回调函数返回 true 的项会保留在数组中,返回 false 的项会被过滤出数组。
var oldArray = [1,2,3,4,5,6,7,8,9,10]
var newArray = oldArray.filter(function(val){
return val<6
})//从数组中选出小于6的元素
reduce(n变1)
数组方法 reduce 用来迭代一个数组,并且把它累积到一个值中。reduce需要传入两个参数,用来代表数组中的值,reduce 方法有一个可选的第二参数,它可以被用来设置累加器的初始值。如果没有在这定义初始值,那么初始值将变成数组中的第一项,而第二个参数 将表示从数组的第二项开始。
var array = [4,5,6,7,8]
var singleVal = 0
singleVal = array.reduce(function(first,second){
return first+second;
},0)//计算数组所有元素的总和
题目:用reduce将数组变成对象
原数组结构:
arr.reduce((result,item)=>{
if(item.parent===null){
result.id=item.id
result['名称']=item['名称']
}else{
result.children.push(item)
delete item.parent
item.children=null
}
return result
}
,{id:null,children:[]})
输出结果: