# JS数组
# 特点
- 元素的数据类型可以不同
- 内存不一定是连续的(对象是随机存储的)
- 不能通过数字下标,而是通过字符串下标
- 数组可以有任何key

# 创建数组
- 新建数组
let arr = [1,2,3]
let arr = new Array(1,2,3)
let arr = new Array(3)     //一个参数表示数组长度

- 转化数组
split()方法使用指定的分隔符字符串将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置。
let arr = '1,2,3'.split(',')
let arr = '123'.split('')

Array.from()方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
Array.from('123')

- 伪数组
伪数组的原型链中并没有数组的原型 没有数组公共属性的数组就是伪数组

- 合并数组
concat()方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变
let a = [1,2,3,4,5];
let b = [6,7,8,9];
console.log(a.concat(b));//[1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(a); //[1, 2, 3, 4, 5]
console.log(b); //[6, 7, 8, 9]
- 截取数组一部分
slice()方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
let arr = [0,1,2,3,4,5,6,7,8];
arr.slice(2); //从第三个元素开始
console.log(arr.slice(2));//[2, 3, 4, 5, 6, 7, 8]
console.log(arr);//[0, 1, 2, 3, 4, 5, 6, 7, 8]
arr.slice(0)   //全部截取
# 删除元素
错误方法 使用
delete arr[0]删除元素并未改变数组长度,若数组全部为空称之为稀疏数组 直接修改arr.length会改变数组,出现意外


正确方法


splice()方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。 参数:开始索引、删除元素的位移、插入的新元素

# 查看元素
- 查看所有属性名
let arr = [1,2,3,4,5]
for(let i in arr){
  console.log(`${i}:${arr[i]}`)
}
Object.keys(arr)

- 查看数字(字符串)属性名和值
let arr1 = [1,2,3,4,5,6]
for(let i=0;i<arr.length;i++){
  console.log(`${i}:${arr[i]}`)
}
arr.forEach(function(item,index){
  console.log(`${index}:${index}`)
})

# 理解forEach
 function forEach(array,fn){
  for(let i=0;i<array.length;i++){
    fn(array[i],i,array)
  }
}
forEach函数使用for循环访问array的每一项 对每一项调用fn(array[i],i,array)

# forEach函数与for循环的区别:
 - for循环作用域为块级作用域,foreach作用域为函数作用域
- 在 for 循环中可以使用 continue,break 来控制循环和跳出循环;forEach 则必须将循环全部执行

- 查看单个属性
let arr = [1,2,3,4,5]
arr[0]
# 索引越界


- 查看某元素是否在数组
indexOf()方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1
arr.indexOf(item)   //存在返回索引,否则返回-1
- 使用条件查找元素
find()方法返回数组中满足提供的测试函数的第一个元素的值。否则返回undefined
arr.find(item => item%2 ===0)   //找第一个偶数
- 使用条件查找元素的索引
findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
arr.findIndex(item => item%2 ===0)    //查找第一个偶数的索引

# 增加元素
- 在头部加元素
arr.unshift(newItem)   //修改arr,返回新长度
arr.unshift(item1,item2)  //修改arr,返回新长度
- 在尾部加元素
arr.push(newitem)   //修改arr,返回新长度
arr.push(item1,item2) //修改arr,返回新长度
- 在中间添加元素
arr.splice(index,0,'x')   //在index处插入'x'
arr.splice(index,0,'x','y')

# 修改元素
- 反转顺序
reverse()方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
arr.reverse()  //修改原数组
a.split('').reverse().join('')  //字符串倒序

- 自定义顺序
sort()方法用原地算法对数组的元素进行排序,并返回数组。
//比较函数
function compare(a, b) {
  if (a < b ) {           // 按某种排序标准进行比较, a 小于 b
    return -1;
  }
  if (a > b ) {
    return 1;
  }
  return 0;
}
如果 compareFunction(a, b) 小于 0 , a 会被排列到 b 之前
如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变
如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前


# 数组变换
- map
Test1:将数组值变为平方
let arr = [1,2,3,4,5]
arr2.map(item => item*item)

Test2:请使用 arr.map 把 0 变成'周日',把 1 变成'周一',以此类推
let arr = [0,1,2,2,3,3,3,4,4,4,4,6]
arr.map( item => { return { 0: '周日', 1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五',6: '周六'}[item]
})
- filter
Test3:取数组偶数
let arr = [1,2,3,4,5,6]
arr.filter(item => item %2 ==0 )

- reduce
Test4:求数组和
let arr = [1,2,3,4,5]
arr.reduce((sum,item)=>{return sum+item},0)

Test5:使用reduce改写map、reduce
let arr = [1,2,3,4,5,6]
arr.reduce((result,item) => {return result.concat(item*item)},[])
arr.reduce((result,item) => {
  if(item % 2 === 1){
    return result
  }else{
    return result.concat(item)
  }
},[])

Test6:数据变换

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:[]})

