一、JS数组不是典型的数组
1.1 典型数组的特征
- 使用一段连续的内存
- 数组中每个元素的类型一样
- 通过数字下标访问元素
- 随机访问的复杂度是O(1)
1.2 JS数组
js数组本质上新建一个对象,用key和value去模拟的
JS数组和典型数组相比,不同点有:
- 内存不一定是连续的,因为对象在JS中是随机存储的
- 元素的数据类型可以不同
- 不能通过数字下标访问,而是通过字符串下标
也就是说数组可以用任何Key
比如let arr = [1, 2, 3]arr['xxx'] = 1
二、创建数组
2.1 从0开始创建数组
- let arr = [1, 2, 3] 【最常用】
- let arr = new Array(1, 2, 3)
2.2从字符串或者伪数组转换为数字
- let arr = '123'.split('')
- let arr= Array.from(伪数组)
2.2.1 Array.from
Array.from可以把字符串和伪数组转换成数组。
2.2.2 什么是伪数组?
伪数组有以下两个特征:
- 对象,且有0, 1, 2, 3作为下标
- 还有length属性
let obj = {0:'a',1:'b',length:2}; // 伪数组
let arr = Array.from(obj)
在创建数组时,array.from会根据length的值裁剪伪数组,例如,如果length写成2,那么就只有['a', 'b']
2.2.3 有哪些常见的伪数组?
调用getElementsByTagName,document.childNodes之类方法,它们都返回NodeList对象都属于伪数组.
2.2.4 伪数组和普通数组的区别?
伪数组和数组的区别在于 伪数组没有含有数组公有属性的原型对象,所以它没有常见的数组操作方法
因此,当我们碰到伪数组时,第一件事就是把它转换成数组
2.3 合并两个数组
把两个数组合并,得到新的数组
用concat方法
concat方法会返回一个新的数组,不影响和修改原先的arr3和arr4
2.4 截取数组中的一部分
slice方法,slice方法的参数是(start, end), 从start开始, 截取到end-1个元素。并且返回一个新数组,不会影响原先的数组
我们还可以用slice(0)复制一个数组
JS没有提供复制数组的方法,所以要想复制数组,只能slice(0)
三、删除数组元素
3.1 会造成灵异事件的删除方法
- 用和删除对象一样的方法来删除:
let arr = ['a', 'b', 'c']
delete arr[0]
这样删除过后,arr会变成[empty, 'b', 'c'],并且arr的length依然是3
- 直接改Length
let arr = ['a', 'b', 'c']
arr.length = 1
这样删除过后,arr会变成['a'],
这种删除方法很不好,所以不要随便改length
3.2 正确的删除数组元素方法
删除头部元素
arr.shift()
arr被修改,并返回被删除的元素
删除尾部元素
arr.pop()
arr被修改,并返回被删除的元素
删除中间元素
arr.splice(index, 1) 删除从Index位置开始的第一个元素
arr.splice(index, 3) 删除从Index位置开始的3个元素
arr.splice(index, 2, 'x') 删除从Index位置开始的2个元素,并添加'x'
四、查看数组里的元素
4.1 查看所有元素
4.1.2 查看数组的所有属性名
这里是按照处理对象的方式来处理数组
第一种
Object.keys(arr)
第二种
for(let key in arr){console.log(`${key}:${arr[key]}`)}
4.1.2 foreach
我们自己实现一个foreach
function forEach(arr, fn) {
for(let i = 0; i < arr.length; i++){
fn(arr[i], i, array)
}
}
foreach的本质就是用for循环访问array的每一项,对每一项调用fn(arr[i], i, array)
4.2 查看单个元素
- arr[0]
- arr.indexOf(item) 查找某个元素在不在数组里
- 用find函数,使用条件查找元素
arr.find(item=>item%2 === 0) 查找第一个偶数 - 使用条件查找元素索引
arr.findIndex(item=>item%2 === 0) 查找第一个偶数的索引
五、增加数组中的元素
5.1 在尾部增加
arr.push(newitem1) 修改arr, 返回新长度
arr.push(item1, item2) 修改arr, 返回新长度
5.2 在头部增加元素
arr.unshift(newitem1) 修改arr, 返回新长度
arr.unshift(item1, item2) 修改arr 返回新长度
5.3 在中间增加元素
arr.splice(index, 0, 'x') // 在Index那里插入x
arr.splice(index, 0, 'x', 'y') // 在Index那里插入x,y
六、数组排序
sort 里写一个函数
let arr = [
{name:'小明', score:99},
{name:'小红', score:83},
{name:'小蓝', score:80},
]
arr.sort(function(a, b){
if (a.score > b.score) {
return -1
} else if (a.score === b.score) {
return 0
} else {
return 1
}
})
console.dir(arr)
这样写是从大到小排序:
而如果把返回值1和-1换一下,就是从小到大排序
arr.sort(function(a, b){
if (a.score > b.score) {
return 1
} else if (a.score === b.score) {
return 0
} else {
return -1
}
})
排序函数里的函数可以简写为:
arr.sort((a, b) => a.score - b.score)
七、数组变换
map n变n
把数字变成日期:
let arr = [0,1,2,2,3,3,3,4,4,4,4,6]
let arr2 = arr.map(补全代码)
console.log(arr2) // ['周日', '周一', '周二', '周二', '周三', '周三', '周三', '周四', '周四', '周四', '周四','周六']
我的写法是要用很多个If else 判断
let arr = [0,1,2,2,3,3,3,4,4,4,4,6]
let arr2 = arr.map(item => {
if (item === 0) {
return '周日'
} else if (item === 1) {
return '周一'
} else if (item === 2) {
return '周二'
} else if (item === 3) {
return '周三'
} else if (item === 4) {
return '周四'
} else {
return '周六'
}
})
console.log(arr2) // ['周日', '周一', '周二', '周二', '周三', '周三', '周三', '周四', '周四', '周四', '周四','周六']
实际上有更简单的写法,直接创造一个对象:
let arr = [0,1,2,2,3,3,3,4,4,4,4,6]
let arr2 = arr.map((i)=>{
return {0:'周日',1:'周一',2:'周二',3:'周三',4:'周四',5:'周五',6:'周六'}[i]
})
console.log(arr2)
filter n变少
筛选出偶数:
挑选出比60高的:
let scores = [95,91,59,55,42,82,72,85,67,66,55,91]
let scores2 = scores.filter(n => n>= 60)
console.log(scores2) // [95,91,82,72,85,67,66, 91]
reduce n变1
developer.mozilla.org/zh-CN/docs/… reduce是数组最厉害的一个api
用reduce实现计算数组每个元素的平方:
挑选出数组中的双数
以上的if else 可以简化为
arr.reduce((result, item) => result.concat(item%2===0? item : [] ), [])
计算所有奇数的和:
let scores = [95,91,59,55,42,82,72,85,67,66,55,91]
let sum = scores.reduce((sum, n)=>{
return n%2===0?sum:sum+n
},0)
console.log(sum) // 奇数之和:598
数组去重:
var myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd'];
var myOrderedArray = myArray.reduce(function (accumulator, currentValue) {
if (accumulator.indexOf(currentValue) === -1) {
accumulator.push(currentValue);
}
return accumulator
}, [])
console.log(myOrderedArray);
计算每个元素在数组中出现的次数:
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
八、一道面试题
let arr = [
{'名称': '动物', id: 1, parent: null},
{'名称': '猫', id: 2, parent: 1},
{'名称': '狗', id: 3, parent: 1}
]
let arr3 = arr.reduce(function (result, item) {
if (item.parent === null) {
result.id = item.id
result['名称'] = item['名称']
} else {
delete item.parent
item.children = null
result.children.push(item)
}
return result
}, {id: null, children: []})
console.dir(arr3)