在编程中,数组是包含元素集合的数据结构。数组非常有用,因为您可以在单个数组中存储、访问和操作多个元素。
在本手册中,您将学习如何在 JavaScript 中使用数组。我们将介绍创建数组时需要遵循的特定规则,以及如何使用数组方法根据需要操作和转换数组。
目录
JavaScript 中数组的工作原理
如何在 JavaScript 中创建数组
如何访问数组的元素
数组长度属性
如何向数组添加元素
如何从数组中删除元素
如何检查变量是否是数组
如何迭代或循环数组
如何将数组转换为字符串
如何比较两个数组
如何复制数组
如何将两个数组合并为一个
如何搜索数组
如何对数组进行排序
如何创建多维数组
在 JavaScript 中,数组被实现为一个对象,该对象可以将一组项目、元素或值作为有序集合。这意味着您可以使用数组中的元素在集合中的位置来访问该元素。在下一节中您将了解为什么这很重要。
数组可以容纳不同数据类型的元素,并且数组的大小不固定。这意味着您可以根据需要向数组添加任意数量的元素。
在 JavaScript 中创建数组有两种方法:
[]
Array()
构造函数方括号[]
是用于创建数组的文字表示法。数组元素在方括号内定义,每个元素使用逗号分隔,
。
以下示例演示如何创建名为 的数组,myArray
该数组包含三个不同类型的元素:数字、字符串和布尔值。
let myArray = [29, 'Nathan', true];
以下是创建包含 3 个数字元素的数组的方法:
let myNumbers = [5, 10, 15];
您可以在方括号内指定任意数量的元素。
创建数组的另一种方法是使用Array()
构造函数,其工作方式类似于方括号:
let myArray = Array(29, 'Nathan', true);
// or
let myNumbers = new Array(5, 10, 15);
请注意,可以使用或不使用new
运算符来调用构造函数。两者都创建了一个数组对象就好了。
在大多数代码示例和代码库中,您很可能会看到开发人员使用方括号来创建数组,而不是使用构造函数。这是因为打字[]
比打字更快Array()
。
正如我之前所说,数组是一个有序集合,因此您可以从数组中的位置(也称为索引号)访问元素。
要访问数组的元素,您需要指定数组名称,后跟方括号。在方括号内,指定要访问的元素的索引。
例如,以下是访问 的第一个元素的方法myArray
:
let myArray = [29, 'Nathan', true];
console.log(myArray[0]); // 29
console.log(myArray[1]); // Nathan
console.log(myArray[2]); // true
数组索引号从 0 开始,每添加到数组中一个元素,索引号就加 1。
如果您尝试访问尚未分配任何值的索引号,JavaScript 将返回undefined
如下所示:
let myArray = [29, 'Nathan', true];
console.log(myArray[3]); // undefined
console.log(myArray[4]); // undefined
console.log(myArray[100]); // undefined
您还可以使用赋值运算符将某个索引号上的元素替换为新元素=
。
以下示例显示如何将第三个元素(布尔值)替换为字符串:
let myArray = [29, 'Nathan', true];
// Replace the third element
myArray[2] = 'Sebhastian';
console.log(myArray); // [ 29, 'Nathan', 'Sebhastian' ]
在上面的示例中,您可以看到true
布尔值被字符串“Sebhastian”替换。接下来我们就来看看楼盘吧length
。
length
属性该length
属性显示数组有多少个元素。您可以使用点.
符号访问此属性,如下所示:
let myArray = [29, 'Nathan', true];
console.log(myArray.length); // 3
let animals = ['Dog', 'Cat'];
console.log(animals.length); // 2
length
每次在数组中添加或删除元素时,该属性都会更新。
要将一个或多个元素添加到数组中,可以使用数组push()
和unshift()
方法。
该push()
方法将新元素添加到数组末尾,而该unshift()
方法将新元素插入数组开头:
let animals = ['Dog', 'Cat'];
animals.push('Horse', 'Fish');
console.log(animals);
// [ 'Dog', 'Cat', 'Horse', 'Fish' ]
animals.unshift('Bird');
console.log(animals);
// [ 'Bird', 'Dog', 'Cat', 'Horse', 'Fish' ]
在这里,请注意,您可以使用逗号来分隔要添加到数组中的元素。
接下来,让我们看看如何从数组中删除元素。
要从数组中删除元素,您可以使用shift()
和pop()
方法,具体取决于要删除的元素的位置。
使用该shift()
方法删除数组中的第一个元素,并使用该方法pop()
删除数组中的最后一个元素:
let animals = ['Dog', 'Cat', 'Horse', 'Fish'];
animals.shift();
console.log(animals);
// [ 'Cat', 'Horse', 'Fish' ]
animals.pop();
console.log(animals);
// [ 'Cat', 'Horse' ]
和一次只能删除一个元素shift()
。pop()
如果要删除数组中间的元素,需要使用该splice()
方法。
splice()
删除或添加元素数组splice()
方法用于删除或添加特定位置的元素。push
当、pop
、shift
、 和unshift
无法完成工作时,可以使用此方法。
要使用该splice()
方法删除元素,您需要指定两个参数:开始数组操作的索引号和要删除的元素数。
例如,假设您要删除animals
数组中索引 1 和 2 处的两个元素。操作方法如下:
let animals = ['Dog', 'Cat', 'Horse', 'Fish'];
animals.splice(1, 2);
console.log(animals);
// [ 'Dog', 'Fish' ]
这splice(1, 2)
意味着从索引 1 开始数组操作,然后从那里删除 2 个元素。
要使用 添加元素splice()
,您需要在第二个参数之后指定要添加的元素。
例如,这里我在索引 1 处添加字符串值“Bird”和“Squid”:
let animals = ['Dog', 'Cat'];
animals.splice(1, 0, 'Bird', 'Squid');
console.log(animals);
// [ 'Dog', 'Bird', 'Squid', 'Cat' ]
如果您不想删除任何元素,可以将其0
作为第二个参数传递给该splice()
方法。然后指定要添加的元素。
splice()
第一次看到该方法时可能会感到困惑,但不用担心!通过更多的练习,你会记住它是如何工作的。
要检查变量是否是数组,可以使用 方法Array.isArray()
来测试提供给该方法的参数是否是数组。
true
当您向该方法传递一个数组时,此方法将返回,false
对于其他任何事情:
let myArray = [1, 2, 3];
let notAnArray = 'Hello!';
console.log(Array.isArray(myArray)); // true
console.log(Array.isArray(notAnArray)); // false
Array
注意,调用方法时需要指定类isArray()
。
这是因为它isArray()
是一个静态方法,因此只能从定义该方法的类中直接调用它。
在 JavaScript 中,有 4 种方法可以迭代数组,具体取决于您使用的方法:
for
循环while
循环for...in
循环for...of
循环forEach()
方法让我们通过示例来学习如何使用这 4 种方法。
要使用循环迭代数组for
,您需要使用数组length
作为条件表达式。
在下面的示例中,for
只要变量i
小于数组的长度,循环就会继续运行:
let animals = ['dog', 'bird', 'cat', 'horse'];
for (let i = 0; i < animals.length; i++) {
console.log(animals[i]);
}
for
您可以在循环体内操作数组的元素。
迭代数组的另一种方法是使用循环while
。您需要使用变量和数组的长度来控制迭代何时停止,就像for
之前的循环一样:
let animals = ['dog', 'bird', 'cat', 'horse'];
let i = 0;
while (i < animals.length) {
console.log(animals[i]);
i++;
}
在 while 循环内,您需要将i
变量加一以避免无限循环。
循环for...in
是另一种可用于迭代数组的语法。该循环返回数组的索引位置,因此您可以像这样使用它:
let animals = ['dog', 'bird', 'cat', 'horse'];
for (i in animals) {
console.log(animals[i]);
}
for...in
与for
or循环相比,该循环更简洁,但在迭代数组时while
最好使用循环。for...of
该for...of
循环可用于迭代数组。它在每次迭代中返回数组的元素:
let animals = ['dog', 'bird', 'cat', 'horse'];
for (element of animals) {
console.log(element);
}
for...in
循环返回索引位置时,for...of
循环直接返回元素。
forEach()
方法JavaScript 数组对象本身有一个名为 的方法forEach()
,您可以使用该方法从位置 0 到最后一个位置迭代数组。
该方法接受在每次迭代中执行的回调函数。对于每次迭代,该方法还传递数组的元素和索引位置。下面是使用该方法的示例:
let animals = ['dog', 'bird', 'cat', 'horse'];
animals.forEach(function (element, index) {
console.log(`${index}: ${element}`);
});
输出将是:
0: dog
1: bird
2: cat
3: horse
这就是使用该方法迭代数组的方式forEach()
。您可以使用您最喜欢的任何方法。
要将数组转换为字符串,可以使用toString()
orjoin()
方法。
该toString()
方法将给定数组转换为字符串,元素之间用逗号分隔:
const animals = ['cat', 'bird', 'fish'];
console.log(animals.toString()); // "cat,bird,fish"
该join()
方法还将数组转换为字符串,但您可以传递特定的字符串分隔符作为其参数。
以下示例显示如何使用斜杠/
和空字符串作为字符串分隔符:
const animals = ['cat', 'bird', 'fish'];
console.log(animals.join()); // "cat,bird,fish"
console.log(animals.join('/')); // "cat/bird/fish"
console.log(animals.join('')); // "catbirdfish"
在幕后,该toString()
方法实际上调用了join()
创建字符串的方法。
JavaScript 数组被视为对象。因此,当您比较两个数组时,比较将查看引用(即存储该数组的内存位置的地址),而不是实际值。
false
即使两个数组包含相同的元素,它们的比较也会返回:
let arrayOne = [7, 8, 9];
let arrayTwo = [7, 8, 9];
console.log(arrayOne === arrayTwo); // false
这是因为arrayOne
和arrayTwo
是存储在不同内存位置的不同对象。
数组比较返回的唯一方法true
是当两个变量引用同一个数组对象时。在下面的示例中,arrayTwo
变量是对 的引用arrayOne
:
let arrayOne = [7, 8, 9];
let arrayTwo = arrayOne;
console.log(arrayOne === arrayTwo); // true
但是,当您需要比较来自不同引用的两个数组时,这将不起作用。比较数组的一种方法是将数组转换为 JSON 对象。
在比较两个不同的数组之前,需要通过调用该JSON.stringify()
方法将它们转换为 JSON 对象。
然后您可以比较两个序列化的字符串,如下所示:
let arrayOne = [7, 8, 9];
let arrayTwo = [7, 8, 9];
console.log(JSON.stringify(arrayOne) === JSON.stringify(arrayTwo)); // true
但此解决方案间接比较数组,并且不同顺序的相同值将返回false
而不是true
.
要以编程方式比较两个数组的元素,您需要使用另一种解决方案。
every()
方法比较数组比较两个数组的另一种方法是使用length
属性和every()
方法的组合。
true
首先,比较数组的长度,以便当第二个数组包含的元素多于第一个数组时,比较不会返回。
之后,您测试第一个数组上的元素是否等于第二个数组上相同索引位置的元素。使用&&
运算符加入比较,如下所示:
let arrayOne = [7, 8, 9];
let arrayTwo = [7, 8, 9];
let result =
arrayOne.length === arrayTwo.length &&
arrayOne.every(function (element, index) {
// compare if the element matches in the same index
return element === arrayTwo[index];
});
console.log(result); // true
这样,您可以比较特定索引处的元素是否确实相等。
尽管如此,此解决方案要求两个数组在某个索引处具有相同的元素才能返回true
.
如果您不关心顺序,只希望两个数组具有相同的元素,则需要使用该includes()
方法而不是相等===
运算符。
includes()
方法比较数组为了比较无序的数组元素,可以使用every()
和includes()
方法的组合。
该includes()
方法测试数组是否具有您指定为其参数的特定元素:
let arrayOne = [7, 8, 9];
let arrayTwo = [9, 7, 8];
let result =
arrayOne.length === arrayTwo.length &&
arrayOne.every(function (element) {
return arrayTwo.includes(element);
});
console.log(result); // true
该方法的另一种替代方法includes()
是使用该indexOf()
方法,该方法返回指定元素的索引。
当未找到该元素时,该indexOf()
方法返回-1
。这意味着您需要在如下所示的情况下every()
退货:true
indexOf(element) !== -1
let arrayOne = [7, 8, 9];
let arrayTwo = [9, 7, 8];
let result =
arrayOne.length === arrayTwo.length &&
arrayOne.every(function (element) {
return arrayTwo.indexOf(element) !== -1;
});
console.log(result); // true
正如您所看到的,比较数组并不简单。您需要创造性地使用数组对象提供的方法。
但别担心!大多数时候,开发 Web 应用程序时不需要比较数组对象。接下来,让我们学习如何复制数组。
复制数组的一种方法是使用slice()
专门为复制数组而提供的方法。
您只需调用该方法并将返回的数组分配给一个新变量,如下所示:
let arrayOne = [7, 8, 9];
let arrayTwo = arrayOne.slice();
console.log(arrayOne); // [ 7, 8, 9 ]
console.log(arrayTwo); // [ 7, 8, 9 ]
但请记住,该slice()
方法返回浅表副本,这意味着副本的值是对原始数组的引用。
当数组包含字符串、数字或布尔值等原始值时,浅复制不会导致问题。但当您复制对象数组时,这可能会成为问题。
为了向您展示我的意思,请参阅下面的示例:
let arrayOne = [{ name: 'Jack', age: 25 }];
let arrayTwo = arrayOne.slice();
console.log(arrayOne); // [ { name: 'Jack', age: 25 } ]
console.log(arrayTwo); // [ { name: 'Jack', age: 25 } ]
arrayTwo[0].name = 'Nathan';
console.log(arrayOne); // [ { name: 'Nathan', age: 25 } ]
console.log(arrayTwo); // [ { name: 'Nathan', age: 25 } ]
你注意到出了什么问题吗?上面的代码只修改了name
的属性arrayTwo
,但它改变了两个数组!
这是因为arrayTwo
是 的浅拷贝arrayOne
。为了防止这种行为,您需要执行深层复制,以便将arrayTwo
值与原始数组断开连接。
要创建数组的深层复制,需要使用JSON.parse()
和JSON.stringify()
方法而不是使用slice()
方法来复制数组。
将JSON.stringify()
数组转换为 JSON 字符串,然后JSON.parse()
将该字符串转换回数组。
由于副本是从 JSON 字符串创建的,因此不再与原始数组有连接:
let arrayOne = [{ name: 'Jack', age: 25 }];
let arrayTwo = JSON.parse(JSON.stringify(arrayOne));
console.log(arrayOne); // [ { name: 'Jack', age: 25 } ]
console.log(arrayTwo); // [ { name: 'Jack', age: 25 } ]
arrayTwo[0].name = 'Nathan';
console.log(arrayOne); // [ { name: 'Jack', age: 25 } ]
console.log(arrayTwo); // [ { name: 'Nathan', age: 25 } ]
在这里,您可以看到更改 的属性arrayTwo
不会更改 中的相同属性arrayOne
。干得好!
JavaScript 提供了一种concat()
方法,可用于将两个或多个数组合并为一个。以下示例演示如何将cats
和birds
数组合并为一个名为 的数组animals
:
let cats = ['tiger', 'cat'];
let birds = ['owl', 'eagle'];
let animals = cats.concat(birds);
console.log(animals); // [ 'tiger', 'cat', 'owl', 'eagle' ]
console.log(cats); // [ 'tiger', 'cat' ]
console.log(birds); // [ 'owl', 'eagle' ]
乍一看,该concat()
方法的语法似乎是将birds
数组合并到cats
数组中。但从控制台日志中可以看到,cats
数组实际上没有变化。
为了使代码更直观,您可以concat()
从空数组而不是cats
数组中调用该方法:
let cats = ['tiger', 'cat'];
let birds = ['owl', 'eagle'];
let animals = [].concat(cats, birds);
虽然这种语法更直观,但您很可能会cats.concat(birds)
在许多 JavaScript 源代码中遇到这种语法。使用哪种语法?这由您和您的团队决定。
该concat()
方法允许您根据需要合并任意数量的数组。以下示例将三个数组合并为一个:
let cats = ['tiger', 'cat'];
let birds = ['owl', 'eagle'];
let dogs = ['wolf', 'dog'];
let animals = [].concat(cats, birds, dogs);
console.log(animals); // [ 'tiger', 'cat', 'owl', 'eagle', 'wolf', 'dog' ]
您现在已经了解了如何使用该concat()
方法合并数组。接下来让我们看看如何使用扩展运算符合并数组。
扩展运算符...
可用于扩展要合并的数组的元素。您需要将扩展的元素放入一个新数组中,如下所示:
let cats = ['tiger', 'cat'];
let birds = ['owl', 'eagle'];
let animals = [...cats, ...birds];
console.log(animals); // [ 'tiger', 'cat', 'owl', 'eagle' ]
cats
在这里,您可以看到和数组中的元素birds
被扩展为另一个数组,并且该数组被分配为变量的值animals
。
该concat()
方法和扩展运算符都可以用来合并多个数组。
您可以通过三种方式搜索数组,具体取决于您想要实现的结果:
让我们一起学习搜索数组的三种方法。别担心,它们很简单。
如果只想知道数组中是否存在某个元素,可以使用该includes()
方法。以下示例在字符串数组中搜索字符串值“e”:
let letters = ['a', 'b', 'c', 'd'];
console.log(letters.include('e')); // false
当找到或未找到元素时,该includes()
方法返回。true
false
其他时候,您可能想要获取元素的索引位置。indexOf()
在这种情况下你需要使用该方法:
let letters = ['a', 'b', 'c', 'd'];
console.log(letters.indexOf('c')); // 2
这里,在数组indexOf()
上调用该方法letters
来搜索值“c”的索引。-1
当未找到元素时该方法返回,但在本例中,它返回2
为字母 c 位于第二个索引处(请记住,JS 使用从零开始的索引,这意味着计数从 0 开始,而不是 1)。
要查找满足特定条件的元素,您需要使用该filter()
方法。
该filter()
方法是可用于 JavaScript 数组对象的内置方法,可以帮助您过滤数组。该方法的语法如下:
arrayObject.filter(callback, thisContext);
该方法有两个参数:
callback
(必需) – 将对每个数组值执行的过滤函数thisContext
(可选this
)-中关键字的值callback
该thisContext
参数是可选的,通常不需要。您只需要定义该callback
函数,该函数将接受三个参数:
currentElement
被处理成方法index
开始于的元素的0
array
你调用的对象filter()
filterCallback(currentElement, index, array){
// ...
}
true
回调函数必须包含返回或 的验证模式false
。
让我们看一个filter()
实际的例子。假设您有一个名为stockPrices
以下的数组:
let stockPrices = [3, 7, 2, 15, 4, 9, 21, 14];
您想要过滤价格以仅包含大于 5 的价格。
以下是使用该filter()
方法的操作方法:
let stockPrices = [3, 7, 2, 15, 4, 9, 21, 14];
let filteredPrices = stockPrices.filter(function (currentElement) {
return currentElement > 5;
});
console.log(filteredPrices); // [7, 15, 9, 21, 14]
该filter()
方法计算currentElement
并返回true
或false
。
如果你的回调函数返回true
,currentElement
将会被添加到结果数组中:
currentElement
返回3
false
currentElement
值推入结果数组7
true
filteredPrices
变量这就是该方法的工作原理。接下来,我们看看如何使用该filter()
方法来过滤对象数组。
该filter()
方法还可以用于对象数组。
假设您有一个包含虚构股票价格及其符号的对象数组,如下所示:
let stocks = [
{
code: 'GOOGL',
price: 1700,
},
{
code: 'AAPL',
price: 130,
},
{
code: 'MSFT',
price: 219,
},
{
code: 'TSLA',
price: 880,
},
{
code: 'FB',
price: 267,
},
{
code: 'AMZN',
price: 3182,
},
];
现在您需要过滤数组以仅包含price
价值小于 1000 的股票。具体操作方法如下:
let filteredStocks = stocks.filter(function (currentElement) {
return currentElement.price < 1000;
});
的值filteredStocks
如下:
0: {code: "AAPL", price: 130}
1: {code: "MSFT", price: 219}
2: {code: "TSLA", price: 880}
3: {code: "FB", price: 267}
最后,您还可以使用箭头函数语法编写回调函数,如下所示:
let filteredStocks = stocks.filter(
currentElement => currentElement.price < 1000
);
当您有简单的过滤条件时,使用箭头函数语法可以帮助您编写更清晰的代码。
要对数组进行排序,可以使用提供的sort()
方法,默认情况下按升序对数组进行排序:
let numbers = [5, 2, 4, 1];
numbers.sort();
console.log(numbers); // [ 1, 2, 4, 5 ]
如果要对数组进行降序排序,可以在该方法reverse()
之后调用该方法sort()
,如下所示:
let numbers = [5, 2, 4, 1];
numbers.sort().reverse();
console.log(numbers); // [ 5, 4, 2, 1 ]
该reverse()
方法将反转数组,因此第一个数组元素变为最后一个,最后一个变为第一个,依此类推。
多维数组是一个包含另一个数组的数组。要创建一个,您需要在数组文字(方括号)内写入一个数组
以下示例展示了如何创建二维数组:
let numbers = [[5, 6, 7]];
要访问数组,只需使用两个数组索引调用变量即可。第一个索引用于外部数组,第二个索引用于内部数组:
let numbers = [[5, 6, 7]];
console.log(numbers[0][0]); // 5
console.log(numbers[0][1]); // 6
console.log(numbers[0][2]); // 7
从上面的示例中可以看出,该数组[5, 6, 7]
存储在0
外部[]
数组的索引内。您可以在数组中添加更多元素,如下所示:
let numbers = [[5, 6, 7], [10], [20]];
console.log(numbers[1][0]); // 10
console.log(numbers[2][0]); // 20
如上所示,多维数组不需要具有相同的数组长度。尽管您甚至可以创建三维或四维数组,但不建议创建二维以上的数组,因为这会造成混乱。
[23]
请注意,读取和访问下面的三维数组内的值是多么困难:
let numbers = [[5, 6, 7, [23]]];
console.log(numbers[0][3][0]); // 23
最后,您仍然可以使用 JavaScriptArray
对象方法,如push()
、shift()
、 和unshift()
来操作多维数组:
let numbers = [[5, 6, 7, [23]]];
numbers.push([50]);
console.log(numbers); // [[5, 6, 7, [23]], [50]]
numbers.shift();
console.log(numbers); // [[50]]
numbers.unshift('13');
console.log(numbers); // ["13", [50]]
与一维数组相比,多维数组没有独特的方法。通常,它用于将一组相关数据存储为一个数组。
以下示例展示了如何对多维数组下的值进行name
分组:age
let users = [
['Nathan', 28],
['Jack', 23],
['Alex', 30],
];
除非必须使用数组,否则最好使用对象数组来存储一组相关数据:
let users = [
{ name: 'Nathan', age: 28 },
{ name: 'Jack', age: 23 },
{ name: 'Alex', age: 30 },
];
理想情况下,您应该在项目中仅使用一维数组。如果确实需要,请使用二维结构,但切勿超出范围,否则稍后操作数组将遇到困难。