数组
数据结构:就是数据元素相互之间存在的一种或多种特定关系的集合。
在JavaScript中共有八种数据结构:
1.数组(Array)
2.栈(stack)
3.队列(Queue)
4.链表(Linked List)
5.散列表(Hash)【哈希表】
6.树(Tree)
7.堆(Heap)
8.图(Graph)
数组的含义与特点、为什么要用数组
什么是数组
- 是最简单、也是使用最广泛的数据结构。
- 数组是可以在内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。
数组的特点
查询快,增删慢
- 查询快:数组的地址是连续的,我们通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素
- 增删慢:数组的长度是固定的,我们想要增加/删除一个元素,必须创建一个新的数组,把原数组的数据复制过来
为什么要用数组
更加简明地呈现信息。const a = 1; const b = 2 const c =3; const Arry = [1,2,3]
数组的声明与初始化
let week = new Array(); //声明数组
week = new Array(7); //创建指定长度数组
week = new Array('Sunday','Monday','Tuesday') //将元素作为参数传递给构造器
最广泛的用法
let week = [];
let week = ['Sunday','Monday','Tuesday']
获取数组长度
let weekLength = ['Sunday','Monday']
let weekLength = week.length() //2
访问数组
用中括号传递数值位置,得到想知道的值
let week = [];
let week = ['Sunday','Monday','Tuesday']
console.log(week[1],week[0]) //Monday,Sunday
迭代访问
let week = [];
let week = ['Sunday','Monday','Tuesday']
for(let i = 0;i < week.length; i++){
console.log(week[i]) //Sunday Monday Tuesday
}
数组的添加
末尾添加
数组长度添加
let num = [0,1,2,3]
num [num .length] = 4
push方法添加
let num = [0,1,2,3]
num.push(4) //[0,1,2,3,4]
num.push(5,6) //[0,1,2,3,4,5,6]
开头添加
自定义方法
定义一个方法,通过for循环,定义起始下标为数组长度,然后循环递减,使遍历后的数组的每一项等于数组没遍历前的每一项,然后第一项会空出来,使其等于传入的值;
let num =[0,1,2,3,4,5,6]
Array.prototype.insertFirstPosition = function(value){ //往原型对象中添加方法
for(let i = this.length;i >=0; i--){
this[i] = this[i-1]
}
this[0] = value
}
num.insertFirstPosition(-1) //[-1,0,1,2,3,4,5,6]
unshift方法
let num = [-1,0,1,2,3,4,5,6]
num.unshift(-2) //[-2,-1,0,1,2,3,4,5,6]
num.unshift(-3,-4) //[-4,-3,-2,-1,0,1,2,3,4,5,6]
数组的删除
末尾删除
使用pop方法
let num = [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6]
let num1 = num.pop();
console.log(num); //[-4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
console.log(num1); //6
开头删除
使用shift删除
let num = [0, 1, 2, 3, 4, 5, 6]
let num1 = num.shift();
console.log(num); //[1, 2, 3, 4, 5, 6]
console.log(num1); //0
任意位置删除和增加
slice截取元素
跟concat一样是创建新数组,并不修改原数组的数据
//第一个参数开始截取的起始下标,包含该下标的数,只有一个参数的话,默认截到结尾
//第二个参数代表结束的下标,不包含
var num = [0,1,2,3,4,5]
var num2 = num.slice(1)
var num3 = num.slice(4,5)
console.log(num); //[0,1,2,3,4,5]
console.log(num2); //[1,2,3,4,5]
console.log(num3); //[4]
splice删除元素
会影响原数组
let num = [0, 1, 2, 3, 4, 5]
num2 = num.splice(1)
console.log(num); //[0]
console.log(num2); //[1,2,3,4,5]
num3 = num2.splice(1, 3)
console.log(num2); //[1,5]
console.log(num3); //[2,3,4]
delete运算符删除元素 [不推荐此用法]
let num = [-3,-2,-1,0,1,5];
let num1 = delete num[0];
console.log(num); //[-2,-1,0,1,5]
console.log(num1); //true
splice添加元素
//第一个参数为要添加的起始下标,
//第二个参数为要删除的个数
//第三个参数后的都为要添加的元素
let num = [-2,-1,0,1,5]
num.splice(0,0,-3) // [-3,-2,-1,0,1,5,6]
num.splice(5,0,2,3,4) //从下标5开始添加3个元素 [-3,-2,-1,0,1,2,3,4,5,6]
num.splice(5,3,2,3) //删除包括下标5开始的3个元素,同时添加一个2个元素 [-3,-2,-1,0,1,2,3,5,6]
数组常用的方法
数组合并【concat】
会创建新数组,对原数组不产生影响
//按传入的顺序合并
const zero = 0;
const oldNum = [1,2,3]
const newNum = [-3,-2,-1]
let numbers = newNum.concat(zero,newNum) //[-3,-2,-1,0,1,2,3]
every方法
对数组中的每个元素运行自己设定的函数。
如果每个元素在定函数中的运行结果为ture,返回ture【全部为true才可以】
否则返回false,结束迭代。
var ages = [32, 33, 16, 40];
ages.every((item)=>{return item>18}) //迭代到16时候就返回 false
some方法
对数组中的每个元素运行自己设定的函数
只要有元素在定函数中的运行结果为ture,则返回true【一个为true就可以】,结束迭代
否则返回false。
var ages = [16, 18, 19, 18];
ages.some((item)=>{return item>18}) //迭代到19的时候就返回 true
forEach方法
与for循环的遍历结果相同
map和filter【会返回新数组】
map
对数组中的每个元素运行自己设定的函数,返回所有调用结果组成的数组
var ages = [32, 33, 16, 40];
ages.map(item=>{return item>18}) //[true,true,false,true]
filter
对数组中的每个元素运行自己设定的函数,返回调用结果为true的元素组成的数组
var ages = [32, 33, 16, 40]
ages.filter(item=>{return item>18}); //[32,33,40]
reduce
对数组的每个元素执行自定义函数;
这个函数返回的任何值都会作为第一个参数自动传给下一项;第一次迭代发生在数组的第二项上,因此第一个参数是数组第一项,第二个参数是数组的第二项;
有四个参数:
- previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
- currentValue (数组中当前被处理的元素)
- index (当前元素在数组中的索引)
- array (调用 reduce 的数组)
var arr = [1, 2, 3, 4];
var sum = arr.reduce((x,y)=>x+y)
var mul = arr.reduce((x,y)=>x*y)
console.log( sum ); //求和,10
console.log( mul ); //求乘积,24
ES6新功能
for…of循环迭代【与for循环跟forEach相同】
const numbers = [1, 2, 3, 4];
for( const n of numbers ){
console.log(n) // 1 2 3 4
}
@@iterator对象
Array类ES6增加一个的属性,可以通过Symbol.iterator来访问,并且用next().value来获取值。【done为false表示还有可以迭代的值】
const numbers = [1, 2, 3, 4];
let iterator = numbers[Symbol.iterator]()
console.log(iterator.next()) //{value: 1, done: false}
for(const n of iterator){
console.log(n) // 2 3 4
}
entries()与keys()、values()
ES6新增加三种从数组种得到迭代器的方法
entries方法返回包含【键值对】的@@iterator对象
const numbers = [1, 2, 3, 4];
let iterator = numbers.entries()
console.log(iterator.next()) //{done: false value: [0, 1]}
for(const n of iterator){
console.log(n) // [1,2] [2,3] [3,4]
}
keys()返回包含数组索引的@@iterator对象
const numbers = [1, 2, 3, 4];
let iterator = numbers.keys()
console.log(iterator.next()) //{value: 0, done: false}
for(const n of iterator){
console.log(n) // 1 2 3
}
values()返回包含数组数值的@@iterator对象
const numbers = [1, 2, 3, 4];
let iterator = numbers.values()
console.log(iterator.next()) //{value: 1, done: false}
for(const n of iterator){
console.log(n) // 2 3 4
}
from方法
将一个类数组对象或者可遍历对象转换成一个真正的数组。
要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
- 该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
- 该类数组对象的属性名必须为数值型或字符串型的数字
let arrayLike = {
0: 'tom',
1: '65',
2: '男',
3: ['jane','john','Mary'],
'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom','65','男',['jane','john','Mary']]
类似于数组的map方法
Array.from还可以接受第二个参数,用来对每个元素进行处理,将处理后的值放入返回的数组。
let arrayLike = [100,200,300]
let arr = Array.from(arrayLike,item=>{return item*2}) //[200, 400, 600]
生成一个一模一样的新数组
参数是一个数组时,Array.from会返回
let arrayLike = [100,200,300]
let arr = Array.from(arrayLike) // [100,200,300]
将字符串转换为数组:
let arrayLike = 'hello word'
let arr = Array.from(arrayLike) //["h", "e", "l", "l", "o", " ", "w", "o", "r", "d"]
Array.of方法
根据传入的参数,创建一个新数组
Array.of(1); // [1]
Array.of(1, 2, 3); // [1, 2, 3]
Array.of(undefined); // [undefined]
也可以跟form一样复制代码
let number = [0,1,2,3,4,5]
let numCopy = Array.of(...number) //[0,1,2,3,4,5]
fill方法【填充】
第一个参数为要填充的值
第二个为开始的下标,第三个是结束的下标
不包括结束的下标,只填充到结束下标前
let number = [0,1,2,3,4,5]
number.fill(0) //[0,0,0,0,0,0]
let number1 = [0,1,2,3,4,5]
number1.fill(1,2) //[0, 1, 1, 1, 1, 1]
let number2 = [0,1,2,3,4,5]
number2.fill(2,3,5) //[0,1,2,2,2,5]
copyWithin方法【复制】
第一个参数为复制结果插入的下标位置 默认从0开始复制
第二个参数为开始复制的下标位置
第三个参数为结束复制的下标位置,包括该下标
const arr = [0, 1, 2, 3, 4, 5, 6];
arr.copyWithin(3) // [0, 1, 2, 0, 1, 2, 3]
const arr1 = [0, 1, 2, 3, 4, 5, 6];
arr1.copyWithin(3, 2) // [0, 1, 2, 2, 3, 4, 5]
const arr2 = [0, 1, 2, 3, 4, 5, 6];
arr2.copyWithin(3, 2, 4) //[0, 1, 2, 2, 3, 5, 6]
数组的排序
reverse
反向排序数组
let num = [1,2,3,4,5]
num.reverse() //[5,4,3,2,1]
sort(升降序)
默认排序
//这里sort元素默认成字符串来比较了
let num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
num.sort() //[1,11,12,13,14,15,2,3,4,5,6,7,8,9]
升序 sort会根据返回值的情况进行对比,我们可以自己写比较函数然后传入
function compare(a,b){
if(a<b){
return -1
}else if(a>b){
return 1
}else{
return 0
}
}
num.sort(compare) //[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
降序
function compare(a,b){
if(a>b){
return -1
}else if(a<b){
return 1
}else{
return 0
}
}
number.sort(compare) //[15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
自定义排序
const person =[
{name:'one',age:'30'},
{name:'tow',age:'10'},
{name:'three',age:'60'},
]
function compare(a,b){
if(a.age>b.age){
return 1
}else if(a.age<b.age){
return -1
}else{
return 0
}
}
person.sort(compare)
//结果为:[{name: "tow", age: "10"},{name: "one", age: "30"},{name: "three", age: "60"}]
数组的搜索
indexOf
返回与参数匹配的第一个元素下标
let number = [0,1,2,3,4,5,6,7,8]
number.indexOf(5); // 5
number.indexOf(100) // -1 因为100不在数组中,找不到时返回-1
lastIndexOf
返回数组中与参数匹配的最后一个元素的下标
let number = [0,1,2,3,4,5,6,7,8]
number.push(5)
number.lastIndexOf(5); // 9
number.indexOf(100) // -1 因为100不在数组中,找不到时返回-1
find和findIndex方法 【ES6搜索方法】
find返回满足搜索条件的第一个值
findIndex 返回满足搜索条件的第一个下标
let number = [1,3,4,5,6,7,8,9,10]
function firstEven(item){
return (item%2 ==0)
}
number.find(firstEven) //4
number.findIndex(firstEven) //2
includes方法 【ES7搜索方法】
let number = [0,1,2,3,4,5,6,7,8]
nummber.includes(15) //false
number.includes(8) //true
number.includes(3,4) //false 第一个参数为要查找的数,第二个为开始查找的下标
toStirng和join
输出数组为字符串
let number = [0,1,2,3,4,5,6,7,8]
number.toString() //0,1,2,3,4,5,6,7,8
number.join('-') //0-1-2-3-4-5-6-7-8
类型化数组[待研究]
为了满足JavaScript与显卡之间大量的、实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文本格式。
比如,以文本格式传递一个32位整数,两端的JavaScript脚本与 显卡都要进行格式转化,非常耗时。这时要是存在一种机制,
可以像C语言那样,直接操作字节,然后将4个字节的32位整数,以二进制形式原封不动的送入显卡,脚本的性能就会大幅提升。
类型化数组就是在这种背景下诞生的。它像C语言的数组,允许开发者以数组下标的形式,直接操作内存。有了类型化数组以后,
JavaScript的二进制数据处理功能增强了很多,接口之间完全可以用二进制数据通信。