js(JavaScript)数据结构之数组(Array)

什么是数据结构?

下面是维基百科的解释:

数据结构是计算机存储、组织数据的方式。数据结构意味着接口或封装:一个数据结构可被视为两个函数之间的接口,或者是由数据类型联合组成的存储内容的访问方法封装。

我们每天的编码中都会用到数据结构,下面是常见的数据结构:

  • 数组(Array)
  • 栈(Stack)
  • 队列(Queue)
  • 链表(Linked List)
  • 散列表(Hash)
  • 字典
  • 树(Tree)
  • 图(Graph)
  • 堆(Heap)

数组(Array)

在计算机科学中,数组数据结构(英语:array data

structure),简称数组(英语:Array),是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)可以计算出该元素对应的存储地址。------维基百科

数组经常使用的场景:待办事项列表、购物清单、最佳十名榜单等等。

数组是计算机科学中的一种数据结构,用于存储一系列相同类型的元素,并将它们存在连续的内存中。通过索引可以找到存储地址。

适用场景

  • 适用:简单数据结构、不需要频繁查找或排序
  • 不适用:复杂数据结构、需要频繁操作和查找

创建数组

  • Array 构造函数:new Array()new Array(1, 2, 3),需要 new 关键字
  • 方括号 [][][1, 2, 3],更简洁

1、Array构造函数

javascript 复制代码
var arr1 = new Array();  //创建空数组
var arr2 = new Array(1,2,3); //创建元素为1,2,3的数组
var arr3 = new Array(5);  //创建长度为5的数组

Array构造函数,需要使用new关键字。

2、使用方括号[]

javascript 复制代码
var arr1 = [] ;  //创建一个空数组
var arr2 = [4,5,6];  //创建元素为4,5,6的数组

判断、长度和遍历数组

  • Array.isArray(arr):判断是否是数组
  • arr.length:获取数组长度
  • 遍历方式:forforEachmapfiltersomeeveryfind

判断是否是数组
Array.isArray(arr) 判断

javascript 复制代码
Array.isArray(arr1);
结果输出为: true

判断数组的长度

数组有一个属性length,可以用来获取数组的长度。

javascript 复制代码
var arr2 = [4,5,6,7];
var length = arr2.length;
结果输出为: 4

遍历数组

方式一:for循环遍历数组

javascript 复制代码
for(var i = 0; i < arr.length; i++) {
	console.log(arr[i]);
}

方式二:forEach遍历数组

forEach()在原数组的基础上改变,没有返回值,在function内进行操作

javascript 复制代码
arr.forEach( function (i) {
    console.log(i);
});

方式三:map遍历数组

map()会返回一个新数组,原数组不会改变。

javascript 复制代码
var arr = [1,2,3];
var arr1 = arr.map(function (i) {
	return i * i;
});
结果:arr1 = [1,4,9]

方式四:filter遍历数组

过滤筛选,返回一个新数组,原数组不会改变。

javascript 复制代码
var arr = [1,2,3,4,5,6,7,8,9];
var arr1 = arr.filter(function(i) {
	return i%2==0;
});
结果:arr1 = [2,4,6,8]

方式五:some遍历检测数组中是否有元素满足条件

如果有一个元素满足条件,则返回true,剩下的元素不会再进行检测

如果全部遍历结束,没有满足条件的元素,则返回false

javascript 复制代码
var arr = [10,17,12,11];
arr.some(function(i){
	return i >15;
);
结果:true

方式六:every遍历检测数组是否所有元素都满足条件

javascript 复制代码
var arr = [17,10,18,15];
arr.every(function(i){
	return i > 11;
});
结果:false

方法七:find遍历返回通过测试的数组的第一个元素的值

当数组中的元素满足条件时,find()返回符合条件的这个元素,剩下的元素不会再进行检测

如果没有符合条件的元素则返回undefined

javascript 复制代码
var arr = [10,12,15,19,111];
arr.find(function(i){
	return i > 14;
});
结果:15

基本操作

  • 读取/查找arr[index]indexOflastIndexOf
  • 更新/替换 :直接赋值或使用 splice()

插入和删除元素

  • 插入unshift()(首部)、push()(尾部)、splice()(中间)
  • 删除pop()(尾部)、shift()(首部)、splice()(中间)
读取元素/查找运算

JavaScript 中通过 数组[下标] 的方式来访问数组中指定下标的元素值,数组下标从0开始。

javascript 复制代码
let arr = [1,5,2,4,4,3,2,14]
console.log(arr[5]) // 3

indexOf()

查找某个字符串在要查询的字符串中首次出现的位置的索引值

javascript 复制代码
var arr = [1,2,3,4,3,2,1];
var n = arr.indexOf(3);
结果: n = 2;

lastIndexOf()

查找某个字符串在要查询的字符串中最后一个出现的索引值

javascript 复制代码
var arr = [1,2,3,4,3,2,1];
var  n = arr.lastIndexOf(3);
结果:n = 4;

注意:如果某字符串中只有一个要查询的字符串,那么lastIndexOf和indexOf结果是一样的。

更新元素/替换元素

数组元素值的更新原理与访问原理一致,也是通过先计算出要更新的内存区域,然后再对其进行修改。

JavaScript 中通过 数组[下标] = 值 的方式对数组中指定位置的值进行修改。

javascript 复制代码
let arr = [1,5,2,4,4,3,2,14]
arr[5] = 100
console.log(arr[5]) // 100

splice()方法

splice(index,length,new_arr)

  • index:从第几个元素开始替换
  • length:需要替换的元素的个数
  • new_arr:替换出来的元素存储在new_arr里

这个方法的返回结果是被截取的部分

javascript 复制代码
使用splice()进行替换:

var arr = [1,2,3,4,5,6];
var arr1 = arr.splice(0,2,9);
结果:arr = [9,3,4,5,6];  arr1 = [1,2];
javascript 复制代码
使用splice()进行删除:

var arr = [1,2,3,4,5,6];
arr.splice(2,3);
结果:arr = [1,2,6];   arr1 = [3,4,5];
javascript 复制代码
使用splice()进行插入:

var arr = [1,2,3,4,5,6];
arr.splice(2,0,10,11,12);
结果:arr = [1,2,10,11,12,3,,4,5,6];
插入元素/添加元素

数组的实际元素数量有可能小于数组的长度

javascript 复制代码
let arr = new Array(8); //定义长度为8的数组,在内存中会为我们分配8个元素的空间

// 初始化:对数组前6个元素赋值
arr[0] = 1;
arr[1] = 5;
arr[2] = 2;
arr[3] = 4;
arr[4] = 4;
arr[5] = 3;

arr.size = 5 // 代表当前数组的实际使用长度

首位插入
unshift()

向数组首位插入元素,可插入多个

javascript 复制代码
var arr = [1,2,3,4,5,6];
arr.unshift(0);
结果:arr = [0,1,2,3,4,5,6];

尾部插入

尾部插入,是最简单的情况,直接把插入的元素放在数组尾部的空闲位置即可,等同于更新元素的操作

如果需要在数组最后插入一个1,直接对当前数组最后一项赋值即可

javascript 复制代码
arr[6] = 1 // 对第6个元素赋值

console.log(arr) // [ 1, 5, 2, 4, 4, 3, 1, <1 empty item> ]

push()

向数组末位插入入元素,可插入多个

javascript 复制代码
var arr = [1,2,3,4,5,6];
arr.push(7);
结果:arr = [1,2,3,4,5,6,7];

配合length使用

向数组末位插入一个元素

javascript 复制代码
var arr = [1,2,3,4,5,6];
ar[arr.length] = 8;
结果:arr = [1,2,3,4,5,6,8];

中间插入

由于数组的每一个元素都有其固定下标,所以不得不首先把插入位置及后面的元素向后移动,腾出地方,再把要插入的元素放到对应的数组位置上;

如果需要在数组第三个位置后插入一个1,那么需要想将第三个位置以及后面的元素全部向后移动一位,留出空闲的位置后再对其进行修改操作。

javascript 复制代码
// 向数组中下标为 index 的位置插入一个item值
function arrayAddItem(arr, index, item) {
    // 将第item后的元素全部向后移动一位
    for(let i = arr.size; i > index; i--){
        // 移动
        arr[i] = arr[i-1]
    }
    
    // 将要插入的值赋值到指定位置
    arr[index] = item
    arr.size++
    
    return arr
}

arr = arrayAddItem(arr, 3, 1)
console.log(arr); // [ 1, 5, 2, 1, 4, 4, 3, <1 empty item> ]

超范围插入

由于数组的长度是不可变的,所以一个数组分配到的内存空间也是固定的。前面都是在数组中元素数量小于数组长度的情况下插入元素的。

javascript 复制代码
let arr = [1,2,3,4,5]
arr.size = 5 // 当前数组是使用长度

// 向数组中下标为 index 的位置插入一个item值
function arrayAddItem(arr, index, item) {
    if(arr[arr.length-1]){
        // 数组中的元素数量已经满了,扩容数组
        arr = expandArray(arr)
    }

    // 将第item后的元素全部向后移动一位
    for(let i = arr.size; i > index; i--){
        // 移动
        arr[i] = arr[i-1]
    }
    // 将要插入的值赋值到指定位置
    arr[index] = item
    arr.size++

    return arr
}

// 扩容数组为原来长度的两倍
function expandArray(arr){
    // 创建一个长度为原来长度两倍的数组
    let newArray = new Array(arr.size * 2)

    // 将原来的数组复制到新的数组中
    for (let i = 0; i < arr.size; i++) {
        newArray[i] = arr[i]
    }
    newArray.size = arr.size

    return newArray
}

arr = arrayAddItem(arr, 3, 1)
console.log(arr); [ 1, 2, 3, 1, 4, 5, <4 empty items>]
删除元素

数组的删除操作和插入操作的过程相反,如果删除的元素位于数组中间,其后的元素都需要向前挪动1位

javascript 复制代码
function arrayRemoveItem(arr, index){
    for (let i = index; i < arr.size-1; i++) {
        // 后面一项往前移动
        arr[i] = arr[i+1]
    }

    // 当前项算法为最后一项
    delete arr[arr.size-1]
    arr.size--
    return arr
}

如果对数组元素没有顺序要求,删除操作还存在一种取巧的方法:

javascript 复制代码
function arrayRemoveItem(arr, index){
    // 最后一项移动到被删除的位置
    arr[index] = arr[size-1]
    // 移除最后一项
    delete arr[size-1]
    size--
    return arr
}

pop()

把数组末尾的元素去除,并返回这个元素

javascript 复制代码
var arr = [1,2,3,4,5,6];
var number = arr.pop();
结果:arr = [1,2,3,4,5]; number = 6;

shift()

把数组开头的元素去除,并返回这个元素

javascript 复制代码
var arr = [1,2,3,4,5,6];
var number = arr.shift();
结果:arr = [2,3,4,5,6]; number = 1;

其他操作

  • 排序和反序sort()reverse()
  • 连接concat()
  • 转换为字符串join()toString()
  • 填充fill()
反序reverse()

用来反转数组的

javascript 复制代码
var arr = [1,2,3,4];
arr.reverse();
结果:arr = [4,3,2,1];
排序sort()

按照字典顺序对元素进行排序,用来排序数组的,并且你也可以自定义排序规则,只需要传入一个函数即可

javascript 复制代码
var arr = [8,5,6,2,3,1];
arr.sort();
结果:arr = [1,2,3,5,6,8];
javascript 复制代码
arr = ['sunshine_lin','sanxin_lin','digger_lin']
console.log(arr.sort())
//['digger_lin','sanxin_lin','sunshine_lin' ]
console.log(arr)
//['digger_lin','sanxin lin','sunshine lin'
console.log(arr.sort((a,b) => b,length - a.length)) // 根据字符串长度排序
//['sunshine_lin','digger_lin','sanxin_lin' ]

console.log(arr)
// [ 'sunshine_lin','digger_lin','sanxin_lin']
连接concat()

连接两个或者多个数组,并且返回该数组。

javascript 复制代码
var arr1 = [1,2,3];
var arr2 = [4,5,6];
arr1.concat(arr2);
结果:arr1 = [1,2,3,4,5,6];
数组转换为字符串

join()

javascript 复制代码
var arr = [1,2,3,4,5];
arr.join();
结果为:"1,2,3,4,5"

toString()

javascript 复制代码
var arr = ["a","b","c","d"];
arr.toString();
结果为:"a,b,c,d"
fill 填充

用来把数组填满成自己想要的元素

javascript 复制代码
arr = ['sunshine_lin','sanxin_lin','digger_lin']
console.log(arr.fill(0))
// [0, 0, 0]
console.log(arr)
// [0, 0, 0]
console.log(new Array(5).fill('哈哈哈哈哈哈'))
//  ['哈哈哈哈哈哈', '哈哈哈哈哈哈', '哈哈哈哈哈哈', '哈哈哈哈哈哈', '哈哈哈哈哈哈']

参考效果

参考代码:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Array操作示例</title>
</head>

<body>
  <script>
    var arr = [1, 2, 3, 4, 5]; // 创建数组

    // 判断、长度和遍历数组
    console.log(Array.isArray(arr)); // true
    console.log(arr.length); // 5
    arr.forEach(function (item) {
      console.log(item);
    });

    // 读取/查找
    console.log(arr[2]); // 3
    console.log(arr.indexOf(4)); // 3
    console.log(arr.lastIndexOf(2)); // 1

    // 更新/替换
    arr[1] = 6;
    console.log(arr); // [1, 6, 3, 4, 5]
    arr.splice(2, 1, 7);
    console.log(arr); // [1, 6, 7, 4, 5]

    // 插入和删除元素
    arr.unshift(0);
    console.log(arr); // [0, 1, 6, 7, 4, 5]
    arr.push(8);
    console.log(arr); // [0, 1, 6, 7, 4, 5, 8]
    arr.splice(3, 0, 9);
    console.log(arr); // [0, 1, 6, 9, 7, 4, 5, 8]
    arr.pop();
    console.log(arr); // [0, 1, 6, 9, 7, 4, 5]
    arr.shift();
    console.log(arr); // [1, 6, 9, 7, 4, 5]
    arr.splice(2, 1);
    console.log(arr); // [1, 6, 7, 4, 5]

    // 其他操作
    arr.sort();
    console.log(arr); // [1, 4, 5, 6, 7]
    arr.reverse();
    console.log(arr); // [7, 6, 5, 4, 1]
    var newArr = arr.concat([2, 3]);
    console.log(newArr); // [7, 6, 5, 4, 1, 2, 3]
    var str = arr.join('-');
    console.log(str); // "7-6-5-4-1"
    arr.fill(0);
    console.log(arr); // [0, 0, 0, 0, 0]
  </script>
</body>

</html>

优势与劣势

  • 优势:快速随机访问、高效的查找(如二分查找)
  • 劣势:插入和删除操作影响性能,需要移动大量元素

适用场景

数组适用于读取操作多、写操作少的情况。

持续学习总结记录中,回顾一下上面的内容:
创建数组

Array 构造函数:new Array() 或 new Array(1, 2, 3),需要 new 关键字

方括号 []:[] 或 [1, 2, 3],更简洁
判断、长度和遍历数组

Array.isArray(arr):判断是否是数组

arr.length:获取数组长度

遍历方式:for、forEach、map、filter、some、every、find
基本操作

读取/查找:arr[index]、indexOf、lastIndexOf

更新/替换:直接赋值或使用 splice()

插入和删除元素

插入:unshift()(首部)、push()(尾部)、splice()(中间)

删除:pop()(尾部)、shift()(首部)、splice()(中间)
其他操作

排序和反序:sort()、reverse()

连接:concat()

转换为字符串:join()、toString()

相关推荐
腾讯TNTWeb前端团队5 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰9 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪9 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy10 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom10 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom10 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom10 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom11 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试