基本数据结构

基本数据结构

介绍

在 JavaScript 和其他编程语言中,我们都可以以多种方式存储和访问数据。本节将教你如何使用数组(array),以及如何访问和复制数组中的信息。本节还将教你如何用点符号和方括号符号来操作和访问 JavaScript 对象(object)中的信息。学习此文档你应该掌握数组和对象的基本属性以及它们之间的区别,并且掌握如何选择它们来实现给定的目标。

使用数组存储数据集合

下面是一个关于数组的更复杂的例子。这是一个多维数组(multi-dimensional Array),或者说是一个包含了其他数组的数组。你可以注意到,在它的内部还包含了 JavaScript 中的对象(objects)结构。我们会在后面的小节中讨论该数据结构,但现在你只需要知道数组能够存储复杂的对象类型数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let complexArray = [
[
{
one: 1,
two: 2
},
{
three: 3,
four: 4
}
],
[
{
a: "a",
b: "b"
},
{
c: "c",
d: “d”
}
]
];

使用 push() 和 unshift() 添加项目到数组中

Array.push()Array.unshift()

这两个方法都接收一个或多个元素作为参数;对一个数组调用这两个方法都可以将输入的元素插入到该数组中;push()方法将元素插入到一个数组的末尾,而unshift()方法将元素插入到一个数组的开头。请看以下例子:

1
2
3
4
5
6
7
8
let twentyThree = 'XXIII';
let romanNumerals = ['XXI', 'XXII'];

romanNumerals.unshift('XIX', 'XX');
// 数组现在为 ['XIX', 'XX', 'XXI', 'XXII']

romanNumerals.push(twentyThree);
// 数组现在为 ['XIX', 'XX', 'XXI', 'XXII', 'XXIII']

注意,我们还可以输入变量,这允许我们很灵活地动态改变我们数组中的数据。

使用 pop() 和 shift() 从数组中删除项目

与前面讲的相反。

作用分别是删除数组最后一个元素和删除数组第一个元素。并返回其值。

使用 splice() 删除项目

在上面的挑战中,我们已经学到了如何利用shift()pop()从数组的开头或者末尾移除元素,但如果我们想移除数组中间的一个元素呢?或者想一次移除多个元素呢?这时候我们就需要splice()了。splice()让我们可以从数组中的任意位置移除任意数量的连续的元素

splice()最多可以接受 3 个参数,但现在我们先关注前两个。splice()接收的前两个参数基于调用splice()数组中元素的索引。splice()的第一个参数代表从数组中的哪个索引开始移除元素,而第二个参数指示要从数组中删除多少个元素。例如:

1
2
3
4
5
let array = ['today', 'was', 'not', 'so', 'great'];

array.splice(2, 2);
// 从第 3 个元素开始,删除 2 个元素
// 现在该数组等于 ['today', 'was', 'great']

splice()不仅从被调用的数组中移除元素,还会返回一个包含被移除元素的数组.

使用 splice() 增加项目

splice()方法可以接受最多 3 个参数,我们现在可以进一步了解splice()。除了移除元素,我们还可以利用它的第三个参数来向数组中添加元素。第三个参数可以是一个或多个元素,这些元素会被添加到数组中。

1
2
3
4
5
6
7
8
9
10
11
function colorChange(arr, index, newColor) {
arr.splice(index, 1, newColor);
return arr;
}

let colorScheme = ['#878787', '#a08794', '#bb7e8c', '#c9b6be', '#d1becf'];

colorScheme = colorChange(colorScheme, 2, '#332327');
// 我们移除了 '#bb7e8c' 并在其位置上添加了 '#332327'
// colorScheme 现在等于 ['#878787', '#a08794', '#332327', '#c9b6be', '#d1becf']

使用 slice() 拷贝数组项目

slice()并不修改数组,而是复制或者说提取(extract)给定数量的元素到一个新数组里,而调用方法的数组则保持不变。slice()只接受 2 个输入参数—第一个是开始提取元素的位置(索引)第二个是结束提取元素的位置(索引)。slice 方法会提取直到该索引的元素,但被提取的元素不包括该索引对应的元素。(不包含后面索引对应的值)请看以下例子:

1
2
3
4
5
let weatherConditions = ['rain', 'snow', 'sleet', 'hail', 'clear'];

let todaysWeather = weatherConditions.slice(1, 3);
// todaysWeather 等于 ['snow', 'sleet'];
// weatherConditions 仍然等于 ['rain', 'snow', 'sleet', 'hail', 'clear']

使用扩展运算符复制数组

1
slice()`已经能让我们从一个数组中选择一些元素来复制到新数组中了,而 ES6 中又新引入了一个简洁且可读性强的语法展开运算符(spread operator),它能让我们方便地复制数组中的*所有*元素。展开语法是这样的:`...

在实践中,我们可以这样用展开运算符来复制一个数组:

1
2
3
4
let thisArray = [true, true, undefined, false, null];
let thatArray = [...thisArray];
// thatArray 等于 [true, true, undefined, false, null]
// thisArray 保持不变,并等于 thatArray

使用 indexOf() 检查元素是否存在

由于数组可以在任意时间被修改或者说被改变(mutated),我们不能保证某个数据在一个给定数组中的位置,甚至不能保证该元素还存在于该数组中。幸运的是,JavaScript 给我们提供了另一个内置方法indexOf()。这个方法让我们可以便捷地检查某个元素是否存在于一个数组中。indexOf()方法接受一个元素作为输入参数,并返回该元素在数组中的位置(索引);若该元素不存在于数组中则返回-1

例如:

1
2
3
4
5
let fruits = ['apples', 'pears', 'oranges', 'peaches', 'pears'];

fruits.indexOf('dates') // 返回 -1
fruits.indexOf('oranges') // 返回 2
fruits.indexOf('pears') // 返回 1,即第一个出现的 'pears' 元素在数组中的索引为 1

使用 For 循环迭代数组的所有项

在进行与数组有关的编程时,我们有时需要遍历数组的所有元素来找出我们需要的元素,或者对数组执行特定的操作。JavaScript 提供了几个内置的方法,它们以不同的方式遍历数组来获得不同的结果(如every()forEach()map()等等)。而简单的for循环不仅能实现这些功能,而且相比之下也更灵活。

请看以下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13

function greaterThanTen(arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] > 10) {
newArr.push(arr[i]);
}
}
return newArr;
}

greaterThanTen([2, 12, 8, 14, 80, 0, 1]);
// 返回 [12, 14, 80]

使用方括号访问属性名称

我们可以使用点操作符和方括号访问对象的属性值。

假设一个超市的收银台的程序中使用了一个foods对象,并且有一些程序逻辑会设置selectedFood,我们需要查询foods对象来检查某种食物是否存在,我们可以这样写检查逻辑:

1
2
let selectedFood = getCurrentFood(scannedItem);
let inventory = foods[selectedFood];

上述代码会先计算selectedFood变量的值,并返回foods对象中以该值命名的属性对应的值,若没有以该值命名的属性则会返回undefined。有时候对象的属性名在运行之前是不确定的,或者我们需要动态地访问对象的属性,这时方括号符号就会很有用。

使用 delete 关键字删除对象属性

果我们想移除apples属性,我们可以使用delete关键字:

1
delete foods.apples;

使用 for…in 语句迭代对象

有时候你需要遍历一个对象中的所有键。这需要 JavaScript 中的一个特殊语法:for…in 语句。以遍历 users对象的键为例:

1
2
3
4
5
6
7
8
9
for (let user in users) {
console.log(user);
};

// 输出:
Alan
Jeff
Sarah
Ryan

在这个语句中,我们定义了一个user变量,你可以看到,这个变量在 for…in 语句对对象的每一个键的遍历中都会被重置。

注意:
跟数组不同,对象中的键是无序的,因此一个对象中某个键的位置,或者说它出现的相对顺序,在引用或访问该键时是不确定的。

使用 Object.keys() 生成对象所有键组成的数组

我们还可以输入一个对象作为参数来调用Object.keys()方法,使其生成一个包含对象中所有键的数组。这会返回一个由对象中所有键的名称(字符串)组成的数组。再次说明,这个数组中的项的顺序是不确定的。