一、数组对象
-
数组对象是一种特殊的对象
-
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.from('123') //把不是数组的东西尝试变成数组,需要满足两个条件:对象有'0''1''2'...下标;有length属性
复制代码
- 伪数组
let divList = document.querySelectorAll('div')
伪数组的原型链中并没有数组的原型,比如push、pop
等共同属性。没有数组共用属性的”数组”就是伪数组。 伪数组没有实际用意,每次遇到伪数组都用Array.from把它转换成数组。
创建一个数组(续)
- 合并两个数组,得到新数组,不会改变原来的数组
arr1.concat(arr2)
- 截取数组的一部分
arr1.slice(1) //从第二个元素开始切,不会改变原来的数据
arr1.slice(0) //常用于复制数组
复制代码
注意:JS提供浅拷贝
三、数组增删改查
删元素
- delet方式
let arr = ['a','b','c']
delete arr['0'] //删除第一个元素
arr //[empty,'b','c'] 数组的长度并没有变,保留了原本元素的位置
delate arr[1]
delate arr[2] //[empty*3] 只有length,但没有对应的下标,称为‘稀疏数组’,多bug
复制代码
以上方法更适用于删除对象,不推荐于在数组中使用。
- 改length删除法
let arr = [1,2,3,4,5];
arr.length = 2
arr //[1,2] 后面的数组元素都会被删除掉,且不会报错,实践中容易出bug
复制代码
!!注意:不要随便改length,以上两种方式:delete / 改length,都不推荐使用
推荐删元素的方式
- 删除头部的元素
arr.shift() //arr被修改,并返回被删的元素
复制代码
- 删除尾部的元素
arr.pop() //arr被修改,并返回被删的元素
复制代码
- 删除中间的元素
arr.splice(index,1) //删除index中的1个元素
arr.splice(index,1,'x') //并在删除位置添加'x'
arr.splice(index,1,'x','y') //并在删除位置添加'x','y'
复制代码
查看所有元素
- 查看所有属性名
let arr = [1,2,3,4,5];arr.x = 'xxx'
Object.keys(arr)
for(let key in arr){console.log(`${key}:${arr[key]}`)}
复制代码
以上for in
方法只适合查看对象,不适合数组,不推荐使用。
推荐for let
查看方法
- 查看数字(字符串)属性名和值
方法一:for循环
for(let i = 0; i < arr.lenght; i++){
console.log(`${i}: ${arr[i]}`)
} //在访问数组的时候,规定好下标必须是从0增长到length-1
复制代码
方法二:用forEach / map等原型上的函数
arr.forEach(function(item, index){
console.log(`${index}: ${item}`)
})
复制代码
这两种方式的区别:
1.for循环里有break和continue,而forEach是不支持的,一次全执行完。
2.for循环是关键字,没有函数作用域,只有块级作用域。forEach是函数,有函数作用域。
如何理解forEach
function forEach(array, fn){
for(let i = 0; i<array.length; i++){
fn(arry[i], i, array)
}
}
复制代码
forEach用for访问array的每一项;
对每一项调用fn(arry[i],i,array),
获取数组里的每一项并把每一项作为fn的参数传给fn。
查看单个属性
- 下标法
let arr = [111,222,333]
arr[0] //111
复制代码
- 索引越界
arr[arr.length] === undefined
arr[-1] === undefined
// 任何不存在的下标去读都是undefined
复制代码
举例
let arr = [1,2,3,4,5,6,7]
for(let i = 0; i<= arr.lenght; i++){ //<=length是不允许的,length值是查不到,只能是length-1
console.log(arr[i].tostring())
}
复制代码
Cannot read property 'toString' of underfined
意思是你读取了undefined
的toString
属性,不是指toString
是undefined
。x.toString()
其中x
如果是undefined
就会出现此报错。
查看单个属性(续)
- 查找某个元素是否在数组里
arr.indexOf(item) //存在返回索引,否则返回-1
复制代码
- 使用条件查找元素
arr.find(item => item %2 ===0) //找第一个偶数
复制代码
但是find
只会返回元素,不会返回下标,可使用findIndex
,返回对应的元素的下标。
- 使用条件查找元素的索引
arr.findIndex(item => item%2 ===0) //找第一个偶数的索引
复制代码
增加数组中的元素
- 在尾部添加元素
arr.push(newItem) //修改arr,返回新length
arr.push(item1,item2) //增加多项,修改arr,返回新length
复制代码
- 在头部添加元素
arr.unshift(newItem) //修改arr,返回新length
arr.unshift(item1,item2) //增加多项,修改arr,返回新length
复制代码
- 在中间添加元素
arr.splice(index,0,'x') //在index处插入'x'
arr.splice(index,0,'x','y')
复制代码
修改数据中的元素
- 替换法
let arr = [11,22,44]
arr[2] = 33 //把下标为2的位置替换成'33'
复制代码
- 反转顺序
arr.reverse() //修改原数组
复制代码
拓展:“如何把字符串反转顺序”
字符串是没有reverse
的,需要把字符串先分开变成数组,再把数组反转顺序,最后合成字符串。
- 自定义顺序
arr.sort((a,b)=> a-b)
复制代码
如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。
如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
如果不设定compareFunction,JS默认为数值小的在前,数值大的在后,eg:1,2,3。但是实际到底谁小谁大,JS是不知道的,需要通过设定1,-1,0来让JS判断。
举例
数组变换
map
n变n
filter
n变少
reduce
(可以代替map和filter,但是对新人不太友好,要多实践)
n变1
代码练习