JS数组
Get Started
• 数组对象
• 增删改查
数组对象
一种特殊的对象
JS其实没有真正的数组,只是用对象模拟数组
JS的数组不是典型的数组
• 典型的数组
元素的数据类型相同
使用连续的内存存储
通过数字下标获取元素
• 但JS 的数组不这样
元素的数据类型可以不同
内存不一定连续(对象是随机存储的)
不能通过数字下标,而是通过字符串下标
这意味着数组可以有任何key
比如
let arr = [1, 2, 3]
arr['xxx'] = 1
创建一个数组
• 新建
let arr = [1, 2, 3]
let arr = new Array(1, 2, 3)
let arr = new Array(3)
• 转化
let arr = '1,2,3'.split(',')
let arr = '123'.split('')
Array.form('123')(有下标,有length)
• 伪数组:有着数组格式的对象
let divList = document.querySelector('div')
伪数组的原型链中并没有数组的原型
• 合并两个数组,返回一个新数组
arr1.concat(arr2)
• 截取一个数组的一部分,并返回(原数组不变)
arr1.slics(1) //从第二个元素开始
arr1.slice(0) //全部截取
注意:JS只提供浅拷贝
split() 方法用于把一个字符串分割成字符串数组
用法:stringObject.split(separator,howmany)
concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
用法:var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
用法:arr.slice([begin[, end]]) (包前不包后)
增删改查
数组中的元素
删
• 跟对象一样
let arr = ['a', 'b', 'c']
delete arr['0']
arr //['empty', 'b', 'c']
• 注意数组的长度并没有变,叫做稀疏数组。
• 直接改length可以删元素
let arr = [1, 2, 3, 4, 5];
arr.length = 1
重要:不要随便改length
推荐
• 删除头部的元素
arr.shift()
shift()方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
• 删除尾部的元素
arr.pop()
pop()方法从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
• 删除中间的元素
arr.splice(index, 1)//删除index(下标)的一个元素
arr.splice(index, 1, 'x')//···并在删除位置添加'x'
arr.splice(index, 1, 'x', 'y')//···并在删除位置添加'x''y'
splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
查看所有元素
• 查看所有属性名
let arr = [1, 2, 3, 4, 5]; arr.x = 'xxx'
Object.keys(arr)//Object.values(arr)
• 适用于对象,返回由key或者value组成的数组。
for(let keyin arr){console.log(`${key}:${arr[key]}`)}
• 查看数字(字符串)属性名和值
for ( let i = 0; I < arr.length; i++ ){
console.log(`${key}:${arr[i]}`)
}
要自己让i从0增长到length-1(遍历)
arr.forEach(function(item, index)){
console.log(`${index}:${item}`)
}
也可以用forEach/map等原型上的函数
• forEach() 方法对数组的每个元素执行一次给定的函数。被调用时,不会改变原数组。
arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
• arr.forEach(function(item, index, array))
数组中正在处理的当前元素,下标,正在操作的数组(放桃子的筐,顺序,一堆桃子)
thisArg可选参数。当执行回调函数 callback 时,用作 this 的值。
返回值:undefined
注意:forEach不支持break和continue
for循环时块级作用域,forEach是函数作用域
• 例一:将 for 循环转换为 forEach
const items = ['item1', 'item2', 'item3'];
const copy = [];
// before
for (let i=0; i<items.length; i++) {
copy.push(items[i]);
}
// after
items.forEach(function(item){
copy.push(item);
});
• 例二:打印出数组的内容
function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// 注意索引 2 被跳过了,因为在数组的这个位置没有项
[2, 5, , 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[3] = 9
• 例三:扁平化数组
function flatten(arr) {
const result = [];
arr.forEach((i) => {
if (Array.isArray(i)){
console.log(i);
result.push(...flatten(i));
}else{
result.push(i);
}
})
return result;
}
// Usage
const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]];
flatten(problem);
>>
(5) [4, 5, Array(2), 8, 9]
(2) [6, 7]
(9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
查看单个属性
• 跟对象一样
let arr = [111, 222, 333]
arr[0]
• 索引越界
arr[arr.length] === undefined
arr[-1] === undefined
• 报错
Cannot read property 'toString' of indefined
意思是你读取了undefined的toString属性,x.toString()中x如果是undefined,就报这个错
• 查找某个元素是否在数组里
arr.indexOf(item) //存在返回索引,否则返回-1
• 使用条件查找元素
arr.find(item => item%2===0)
//查找第一个偶数
• 使用条件查找元素的索引
arr.findIndex(item => item%2===0)
//查找第一个偶数的索引
增加数组中的元素
• 在尾部加元素
arr.push(newItem) //修改arr,返回新长度
arr.push(item1, item2) //修改arr,返回新长度
• 在头部加元素
arr.unshift(newItem) //修改arr,返回新长度
arr.unshift(item1, item2) //修改arr,返回新长度
• 在中间添加元素
arr.splice(index, 0, 'x') //在index处插入'x'
arr.splice(index, 0, 'x', 'y')
修改数组中元素的顺序
• 反转顺序
arr.reverse() //修改原数组
• 自定义顺序
arr.sort((a, b) => a - b)
数组变换
map() 方法
创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
• n变n
• 语法
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
• 数组中正在处理的当前元素,下标,正在操作的数组(放桃子的筐,顺序,一堆桃子)
• 例子
let arr = [0,1,2,2,3,3,3,4,4,4,4,6]
let arr2 = arr.map((i) => {
const date = {0:'周日', 1: '周一', 2: '周二',3: '周三', 4: '周四', 5: '周五', 6: '周六'}
return date[i]
})
console.log(arr2) // ['周日', '周一', '周二', '周二', '周三', '周三', '周三', '周四', '周四', '周四', '周四','周六']
filter() 方法
创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
filter 不会改变原数组,它返回过滤后的新数组。
• n变少
• 语法
var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
• 例子
let scores = [95,91,59,55,42,82,72,85,67,66,55,91]
let scores2 = scores.filter(item => item/60 >= 1)
console.log(scores2) // [95,91,82,72,85,67,66, 91]
reduce() 方法
对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
• n变1
• 语法
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
• accumulator
累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue
• 例子
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
面试题
• 数据变换
let arr = [
{名称: '动物', id: 1, parent: null},
{名称: '狗', id: 2, parent: null},
{名称: '猫', id: 3, parent: null}
]
数组变成对象
{
id: 1, 名称: '动物', children:[
{id: 2, 名称: '狗', children: null},
{id: 3, 名称: '猫', children: null}
]
}
• 代码
arr.reduce((result, item) => {
if( item['名称'] === '动物' ) {
result.id = item.id
result['名称'] = item['名称']
} else {
result.children.push(item)
delete item.parent
item.chilred = null
}
return result
},{id:null, children: []})