数组

在本模块的最后一篇文章中,我们将介绍数组 - 一种在单个变量名称下存储数据项列表的巧妙方法。在这里,我们看看为什么它很有用,然后探索如何创建数组、检索、添加和删除存储在数组中的项目等等。

¥In the final article of this module, we'll look at arrays — a neat way of storing a list of data items under a single variable name. Here we look at why this is useful, then explore how to create an array, retrieve, add, and remove items stored in an array, and more besides.

先决条件: 对 HTML 和 CSS 有基本的了解,对 JavaScript 有了解。
目标: 了解什么是数组以及如何在 JavaScript 中操作它们。

什么是数组?

¥What is an array?

数组一般描述为 "类似列表的对象";它们基本上是包含存储在列表中的多个值的单个对象。数组对象可以存储在变量中,并以与任何其他类型的值大致相同的方式处理,不同之处在于我们可以单独访问列表中的每个值,并对列表执行超级有用且高效的操作,例如循环 它并对每个值做同样的事情。也许我们有一系列产品及其价格存储在一个数组中,我们希望循环遍历所有产品并将它们打印在发票上,同时将所有价格加在一起并在底部打印出总价格。

¥Arrays are generally described as "list-like objects"; they are basically single objects that contain multiple values stored in a list. Array objects can be stored in variables and dealt with in much the same way as any other type of value, the difference being that we can access each value inside the list individually, and do super useful and efficient things with the list, like loop through it and do the same thing to every value. Maybe we've got a series of product items and their prices stored in an array, and we want to loop through them all and print them out on an invoice, while totaling all the prices together and printing out the total price at the bottom.

如果我们没有数组,我们就必须将每个项目存储在一个单独的变量中,然后调用为每个项目单独进行打印和添加的代码。这样写起来会更长,效率更低,而且更容易出错。如果我们要在发票中添加 10 个项目,那就已经很烦人了,但是 100 个项目或 1000 个项目呢?我们稍后将在本文中返回这个示例。

¥If we didn't have arrays, we'd have to store every item in a separate variable, then call the code that does the printing and adding separately for each item. This would be much longer to write out, less efficient, and more error-prone. If we had 10 items to add to the invoice it would already be annoying, but what about 100 items, or 1000? We'll return to this example later on in the article.

和之前的文章一样,让我们通过在 浏览器开发者控制台 中输入一些示例来了解数组的真正基础知识。

¥As in previous articles, let's learn about the real basics of arrays by entering some examples into browser developer console.

创建数组

¥Creating arrays

数组由方括号和用逗号分隔的项目组成。

¥Arrays consist of square brackets and items that are separated by commas.

  1. 假设我们想将购物清单存储在数组中。将以下代码粘贴到控制台中:
    js
    const shopping = ["bread", "milk", "cheese", "hummus", "noodles"];
    console.log(shopping);
    
  2. 在上面的示例中,每个项目都是一个字符串,但在数组中我们可以存储各种数据类型 - 字符串、数字、对象,甚至其他数组。我们还可以在单个数组中混合数据类型 - 我们不必限制自己在一个数组中仅存储数字,而在另一个数组中仅存储字符串。例如:
    js
    const sequence = [1, 1, 2, 3, 5, 8, 13];
    const random = ["tree", 795, [0, 1, 2]];
    
  3. 在继续之前,创建一些示例数组。

查找数组的长度

¥Finding the length of an array

你可以通过使用 length 属性以与查找字符串长度(以字符为单位)完全相同的方式查找数组的长度(其中有多少项)。请尝试以下操作:

¥You can find out the length of an array (how many items are in it) in exactly the same way as you find out the length (in characters) of a string — by using the length property. Try the following:

js
const shopping = ["bread", "milk", "cheese", "hummus", "noodles"];
console.log(shopping.length); // 5

访问和修改数组项

¥Accessing and modifying array items

数组中的项目从零开始编号。这个数字称为该项目的索引。因此第一项的索引为 0,第二项的索引为 1,依此类推。你可以使用括号表示法并提供项目索引来访问数组中的各个项目,就像 访问字符串中的字母

¥Items in an array are numbered, starting from zero. This number is called the item's index. So the first item has index 0, the second has index 1, and so on. You can access individual items in the array using bracket notation and supplying the item's index, in the same way that you accessed the letters in a string.

  1. 在控制台中输入以下内容:
    js
    const shopping = ["bread", "milk", "cheese", "hummus", "noodles"];
    console.log(shopping[0]);
    // returns "bread"
    
  2. 你还可以通过为单个数组项赋予新值来修改数组中的项。尝试这个:
    js
    const shopping = ["bread", "milk", "cheese", "hummus", "noodles"];
    shopping[0] = "tahini";
    console.log(shopping);
    // shopping will now return [ "tahini", "milk", "cheese", "hummus", "noodles" ]
    

    注意:我们之前已经说过,但只是提醒一下 - 计算机从 0 开始计数!

    ¥Note: We've said it before, but just as a reminder — computers start counting from 0!

  3. 请注意,数组内的数组称为多维数组。你可以通过将两组方括号链接在一起来访问本身位于另一个数组内的数组内的项目。例如,要访问数组中的一项(即 random 数组中的第三项)(请参阅上一节),我们可以执行以下操作:
    js
    const random = ["tree", 795, [0, 1, 2]];
    random[2][2];
    
  4. 在继续之前,尝试对数组示例进行更多修改。尝试一下,看看哪些有效,哪些无效。

查找数组中项目的索引

¥Finding the index of items in an array

如果你不知道某项的索引,可以使用 indexOf() 方法。indexOf() 方法将一个项目作为参数,并且将返回该项目的索引,如果该项目不在数组中,则返回 -1

¥If you don't know the index of an item, you can use the indexOf() method. The indexOf() method takes an item as an argument and will either return the item's index or -1 if the item is not in the array:

js
const birds = ["Parrot", "Falcon", "Owl"];
console.log(birds.indexOf("Owl")); //  2
console.log(birds.indexOf("Rabbit")); // -1

添加项目

¥Adding items

要将一项或多项添加到数组末尾,我们可以使用 push()。请注意,你需要包含一个或多个要添加到数组末尾的项目。

¥To add one or more items to the end of an array we can use push(). Note that you need to include one or more items that you want to add to the end of your array.

js
const cities = ["Manchester", "Liverpool"];
cities.push("Cardiff");
console.log(cities); // [ "Manchester", "Liverpool", "Cardiff" ]
cities.push("Bradford", "Brighton");
console.log(cities); // [ "Manchester", "Liverpool", "Cardiff", "Bradford", "Brighton" ]

方法调用完成后,将返回数组的新长度。如果你想将新的数组长度存储在变量中,你可以这样做:

¥The new length of the array is returned when the method call completes. If you wanted to store the new array length in a variable, you could do something like this:

js
const cities = ["Manchester", "Liverpool"];
const newLength = cities.push("Bristol");
console.log(cities); // [ "Manchester", "Liverpool", "Bristol" ]
console.log(newLength); // 3

要将项目添加到数组的开头,请使用 unshift()

¥To add an item to the start of the array, use unshift():

js
const cities = ["Manchester", "Liverpool"];
cities.unshift("Edinburgh");
console.log(cities); // [ "Edinburgh", "Manchester", "Liverpool" ]

移除物品

¥Removing items

要从数组中删除最后一项,请使用 pop()

¥To remove the last item from the array, use pop().

js
const cities = ["Manchester", "Liverpool"];
cities.pop();
console.log(cities); // [ "Manchester" ]

pop() 方法返回被删除的项目。要将该项保存在新变量中,你可以这样做:

¥The pop() method returns the item that was removed. To save that item in a new variable, you could do this:

js
const cities = ["Manchester", "Liverpool"];
const removedCity = cities.pop();
console.log(removedCity); // "Liverpool"

要从数组中删除第一项,请使用 shift()

¥To remove the first item from an array, use shift():

js
const cities = ["Manchester", "Liverpool"];
cities.shift();
console.log(cities); // [ "Liverpool" ]

如果你知道某个项目的索引,则可以使用 splice() 将其从数组中删除:

¥If you know the index of an item, you can remove it from the array using splice():

js
const cities = ["Manchester", "Liverpool", "Edinburgh", "Carlisle"];
const index = cities.indexOf("Liverpool");
if (index !== -1) {
  cities.splice(index, 1);
}
console.log(cities); // [ "Manchester", "Edinburgh", "Carlisle" ]

在对 splice() 的调用中,第一个参数表示从哪里开始删除项目,第二个参数表示应删除多少项目。因此你可以删除多个项目:

¥In this call to splice(), the first argument says where to start removing items, and the second argument says how many items should be removed. So you can remove more than one item:

js
const cities = ["Manchester", "Liverpool", "Edinburgh", "Carlisle"];
const index = cities.indexOf("Liverpool");
if (index !== -1) {
  cities.splice(index, 2);
}
console.log(cities); // [ "Manchester", "Carlisle" ]

访问每个项目

¥Accessing every item

很多时候,你会想要访问数组中的每个项目。你可以使用 for...of 语句来执行此操作:

¥Very often you will want to access every item in the array. You can do this using the for...of statement:

js
const birds = ["Parrot", "Falcon", "Owl"];

for (const bird of birds) {
  console.log(bird);
}

有时你可能希望对数组中的每个项目执行相同的操作,从而留下一个包含更改项目的数组。你可以使用 map() 来完成此操作。下面的代码采用一个数字数组并将每个数字加倍:

¥Sometimes you will want to do the same thing to each item in an array, leaving you with an array containing the changed items. You can do this using map(). The code below takes an array of numbers and doubles each number:

js
function double(number) {
  return number * 2;
}
const numbers = [5, 2, 7, 6];
const doubled = numbers.map(double);
console.log(doubled); // [ 10, 4, 14, 12 ]

我们给 map() 一个函数,map() 对数组中的每个项目调用该函数一次,并传入该项目。然后它将每个函数调用的返回值添加到一个新数组中,最后返回新数组。

¥We give a function to the map(), and map() calls the function once for each item in the array, passing in the item. It then adds the return value from each function call to a new array, and finally returns the new array.

有时你需要创建一个新数组,仅包含原始数组中与某些测试匹配的项目。你可以使用 filter() 来做到这一点。下面的代码接受一个字符串数组并返回一个仅包含长度大于 8 个字符的字符串的数组:

¥Sometimes you'll want to create a new array containing only the items in the original array that match some test. You can do that using filter(). The code below takes an array of strings and returns an array containing just the strings that are greater than 8 characters long:

js
function isLong(city) {
  return city.length > 8;
}
const cities = ["London", "Liverpool", "Totnes", "Edinburgh"];
const longer = cities.filter(isLong);
console.log(longer); // [ "Liverpool", "Edinburgh" ]

map() 一样,我们给 filter() 方法一个函数,filter() 为数组中的每个项目调用这个函数,并传入该项目。如果函数返回 true,则该项目将添加到新数组中。最后它返回新数组。

¥Like map(), we give a function to the filter() method, and filter() calls this function for every item in the array, passing in the item. If the function returns true, then the item is added to a new array. Finally it returns the new array.

字符串和数组之间的转换

¥Converting between strings and arrays

通常,你会看到一些包含在长字符串中的原始数据,并且你可能希望将有用的项目分离成更有用的形式,然后对它们进行处理,例如将它们显示在数据表中。为此,我们可以使用 split() 方法。在最简单的形式中,它采用单个参数,即要分隔字符串的字符,并将分隔符之间的子字符串作为数组中的项目返回。

¥Often you'll be presented with some raw data contained in a big long string, and you might want to separate the useful items out into a more useful form and then do things to them, like display them in a data table. To do this, we can use the split() method. In its simplest form, this takes a single parameter, the character you want to separate the string at, and returns the substrings between the separator as items in an array.

注意:好吧,从技术上讲,这是一个字符串方法,而不是数组方法,但我们将它与数组一起放入,因为它在这里运行良好。

¥Note: Okay, this is technically a string method, not an array method, but we've put it in with arrays as it goes well here.

  1. 让我们来玩一下这个,看看它是如何工作的。首先,在控制台中创建一个字符串:
    js
    const data = "Manchester,London,Liverpool,Birmingham,Leeds,Carlisle";
    
  2. 现在让我们在每个逗号处将其分开:
    js
    const cities = data.split(",");
    cities;
    
  3. 最后,尝试查找新数组的长度,并从中检索一些项目:
    js
    cities.length;
    cities[0]; // the first item in the array
    cities[1]; // the second item in the array
    cities[cities.length - 1]; // the last item in the array
    
  4. 你也可以使用 join() 方法进行相反的操作。请尝试以下操作:
    js
    const commaSeparated = cities.join(",");
    commaSeparated;
    
  5. 将数组转换为字符串的另一种方法是使用 toString() 方法。toString() 可以说比 join() 更简单,因为它不接受参数,但限制更多。使用 join(),你可以指定不同的分隔符,而 toString() 始终使用逗号。(尝试使用不同于逗号的字符运行步骤 4。)
    js
    const dogNames = ["Rocket", "Flash", "Bella", "Slugger"];
    dogNames.toString(); // Rocket,Flash,Bella,Slugger
    

主动学习:打印这些产品

¥Active learning: Printing those products

让我们回到前面描述的示例 - 在发票上打印产品名称和价格,然后合计价格并将其打印在底部。在下面的可编辑示例中,有一些包含数字的注释 - 每个注释都标记了你必须在代码中添加某些内容的位置。它们如下:

¥Let's return to the example we described earlier — printing out product names and prices on an invoice, then totaling the prices and printing them at the bottom. In the editable example below there are comments containing numbers — each of these marks a place where you have to add something to the code. They are as follows:

  1. // number 1 注释下方是许多字符串,每个字符串都包含产品名称和价格,并用冒号分隔。我们希望你将其转换为数组并将其存储在名为 products 的数组中。
  2. // number 2 注释下方,启动 for...of() 循环以遍历 products 数组中的每个项目。
  3. // number 3 注释下方,我们希望你编写一行代码,将当前数组项 (name:price) 拆分为两个单独的项,一个仅包含名称,另一个仅包含价格。如果你不确定如何执行此操作,请参阅 有用的字符串方法 文章以获取帮助,或者更好地查看本文的 字符串和数组之间的转换 部分。
  4. 作为上述代码行的一部分,你还需要将价格从字符串转换为数字。如果你不记得如何执行此操作,请查看 第一篇弦文章
  5. 在代码顶部创建了一个名为 total 的变量,并为其赋予了值 0。在循环内部(// number 4 以下),我们希望你添加一行,在循环的每次迭代中将当前商品价格添加到总计中,以便在代码末尾将正确的总计打印到发票上。你可能需要 赋值运算符 才能执行此操作。
  6. 我们希望你更改 // number 5 正下方的行,使 itemText 变量等于 "当前商品名称 - $当前商品价格",例如每种情况下的 "鞋子 — 23.99 美元",以便在发票上打印每个项目的正确信息。这只是简单的字符串连接,你应该很熟悉。
  7. 最后,在 // number 6 注释下方,你需要添加 } 来标记 for...of() 循环的结束。
html
<h2>Live output</h2>

<div class="output" style="min-height: 150px;">
  <ul></ul>

  <p></p>
</div>

<h2>Editable code</h2>

<p class="a11y-label">
  Press Esc to move focus away from the code area (Tab inserts a tab character).
</p>

<textarea id="code" class="playable-code" style="height: 410px;width: 95%">
const list = document.querySelector('.output ul');
const totalBox = document.querySelector('.output p');
let total = 0;
list.innerHTML = '';
totalBox.textContent = '';
// number 1
                'Underpants:6.99'
                'Socks:5.99'
                'T-shirt:14.99'
                'Trousers:31.99'
                'Shoes:23.99';

// number 2

  // number 3

  // number 4

  // number 5
  let itemText = 0;

  const listItem = document.createElement('li');
  listItem.textContent = itemText;
  list.appendChild(listItem);

// number 6

totalBox.textContent = 'Total: $' + total.toFixed(2);
</textarea>

<div class="playable-buttons">
  <input id="reset" type="button" value="Reset" />
  <input id="solution" type="button" value="Show solution" />
</div>
js
const textarea = document.getElementById("code");
const reset = document.getElementById("reset");
const solution = document.getElementById("solution");
let code = textarea.value;
let userEntry = textarea.value;

function updateCode() {
  eval(textarea.value);
}

reset.addEventListener("click", () => {
  textarea.value = code;
  userEntry = textarea.value;
  solutionEntry = jsSolution;
  solution.value = "Show solution";
  updateCode();
});

solution.addEventListener("click", () => {
  if (solution.value === "Show solution") {
    textarea.value = solutionEntry;
    solution.value = "Hide solution";
  } else {
    textarea.value = userEntry;
    solution.value = "Show solution";
  }
  updateCode();
});

const jsSolution = `const list = document.querySelector('.output ul');
const totalBox = document.querySelector('.output p');
let total = 0;
list.innerHTML = '';
totalBox.textContent = '';

const products = [
  'Underpants:6.99',
  'Socks:5.99',
  'T-shirt:14.99',
  'Trousers:31.99',
  'Shoes:23.99',
];

for (const product of products) {
  const subArray = product.split(':');
  const name = subArray[0];
  const price = Number(subArray[1]);
  total += price;
  const itemText = \`\${name} — $\${price}\`;

  const listItem = document.createElement('li');
  listItem.textContent = itemText;
  list.appendChild(listItem);
}

totalBox.textContent = \`Total: $\${total.toFixed(2)}\`;`;
let solutionEntry = jsSolution;

textarea.addEventListener("input", updateCode);
window.addEventListener("load", updateCode);

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead

const KEY_TAB = 9;
const KEY_ESC = 27;

textarea.onkeydown = (event) => {
  if (event.keyCode === KEY_TAB) {
    event.preventDefault();
    insertAtCaret("\t");
  }
  if (event.keyCode === KEY_ESC) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  const scrollPos = textarea.scrollTop;
  let caretPos = textarea.selectionStart;
  const front = textarea.value.substring(0, caretPos);
  const back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );

  textarea.value = front + text + back;
  caretPos += text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

// Update the saved userCode every time the user updates the text area code

textarea.onkeyup = () => {
  // We only want to save the state when the user code is being shown,
  // not the solution, so that solution is not saved over the user code
  if (solution.value === "Show solution") {
    userEntry = textarea.value;
  } else {
    solutionEntry = textarea.value;
  }
  updateCode();
};
css
html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}

.a11y-label {
  margin: 0;
  text-align: right;
  font-size: 0.7rem;
  width: 98%;
}

body {
  margin: 10px;
  background-color: #f5f9fa;
}

主动学习:前 5 名搜索

¥Active learning: Top 5 searches

当你在 Web 应用中维护当前活动项目的记录时,像 push()pop() 这样的数组方法的一个很好的用途。例如,在动画场景中,你可能有一个代表当前显示的背景图形的对象数组,出于性能或混乱的原因,你可能只希望一次显示 50 个。当新对象被创建并添加到数组中时,可以从数组中删除旧对象以维持所需的数量。

¥A good use for array methods like push() and pop() is when you are maintaining a record of currently active items in a web app. In an animated scene for example, you might have an array of objects representing the background graphics currently displayed, and you might only want 50 displayed at once, for performance or clutter reasons. As new objects are created and added to the array, older ones can be deleted from the array to maintain the desired number.

在此示例中,我们为你提供了一个带有搜索框的虚假搜索网站。这个想法是,当在搜索框中输入术语时,前 5 个搜索术语将显示在列表中。当术语数量超过 5 时,每次将新术语添加到顶部时,最后一个术语就会开始被删除,因此始终显示前 5 个术语。

¥In this example we're going to show a much simpler use — here we're giving you a fake search site, with a search box. The idea is that when terms are entered in the search box, the top 5 previous search terms are displayed in the list. When the number of terms goes over 5, the last term starts being deleted each time a new term is added to the top, so the 5 previous terms are always displayed.

注意:在真正的搜索应用中,你可能可以单击以前的搜索词返回到以前的搜索,并且它会显示实际的搜索结果!我们现在只是保持简单。

¥Note: In a real search app, you'd probably be able to click the previous search terms to return to previous searches, and it would display actual search results! We are just keeping it simple for now.

要完成该应用,我们需要你:

¥To complete the app, we need you to:

  1. // number 1 注释下方添加一行,将搜索输入中输入的当前值添加到数组的开头。这可以使用 searchInput.value 检索。
  2. // number 2 注释下方添加一行,删除当前位于数组末尾的值。
html
<h2>Live output</h2>
<div class="output" style="min-height: 150px;">
  <input type="text" /><button>Search</button>

  <ul></ul>
</div>

<h2>Editable code</h2>

<p class="a11y-label">
  Press Esc to move focus away from the code area (Tab inserts a tab character).
</p>

<textarea id="code" class="playable-code" style="height: 370px; width: 95%">
const list = document.querySelector('.output ul');
const searchInput = document.querySelector('.output input');
const searchBtn = document.querySelector('.output button');

list.innerHTML = '';

const myHistory = [];
const MAX_HISTORY = 5;

searchBtn.onclick = () => {
  // we will only allow a term to be entered if the search input isn't empty
  if (searchInput.value !== '') {
    // number 1

    // empty the list so that we don't display duplicate entries
    // the display is regenerated every time a search term is entered.
    list.innerHTML = '';

    // loop through the array, and display all the search terms in the list
    for (const itemText of myHistory) {
      const listItem = document.createElement('li');
      listItem.textContent = itemText;
      list.appendChild(listItem);
    }

    // If the array length is 5 or more, remove the oldest search term
    if (myHistory.length >= MAX_HISTORY) {
      // number 2
    }

    // empty the search input and focus it, ready for the next term to be entered
    searchInput.value = '';
    searchInput.focus();
  }
}
</textarea>

<div class="playable-buttons">
  <input id="reset" type="button" value="Reset" />
  <input id="solution" type="button" value="Show solution" />
</div>
css
html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}

.a11y-label {
  margin: 0;
  text-align: right;
  font-size: 0.7rem;
  width: 98%;
}

body {
  margin: 10px;
  background: #f5f9fa;
}
js
const textarea = document.getElementById("code");
const reset = document.getElementById("reset");
const solution = document.getElementById("solution");
let code = textarea.value;
let userEntry = textarea.value;

function updateCode() {
  eval(textarea.value);
}

reset.addEventListener("click", () => {
  textarea.value = code;
  userEntry = textarea.value;
  solutionEntry = jsSolution;
  solution.value = "Show solution";
  updateCode();
});

solution.addEventListener("click", () => {
  if (solution.value === "Show solution") {
    textarea.value = solutionEntry;
    solution.value = "Hide solution";
  } else {
    textarea.value = userEntry;
    solution.value = "Show solution";
  }
  updateCode();
});

const jsSolution = `const list = document.querySelector('.output ul');
const searchInput = document.querySelector('.output input');
const searchBtn = document.querySelector('.output button');

list.innerHTML = '';

const myHistory = [];
const MAX_HISTORY = 5;

searchBtn.onclick = () => {
  // we will only allow a term to be entered if the search input isn't empty
  if (searchInput.value !== '') {
    myHistory.unshift(searchInput.value);

    // empty the list so that we don't display duplicate entries
    // the display is regenerated every time a search term is entered.
    list.innerHTML = '';

    // loop through the array, and display all the search terms in the list
    for (const itemText of myHistory) {
      const listItem = document.createElement('li');
      listItem.textContent = itemText;
      list.appendChild(listItem);
    }

    // If the array length is 5 or more, remove the oldest search term
    if (myHistory.length >= MAX_HISTORY) {
      myHistory.pop();
    }

    // empty the search input and focus it, ready for the next term to be entered
    searchInput.value = '';
    searchInput.focus();
  }
}`;
let solutionEntry = jsSolution;

textarea.addEventListener("input", updateCode);
window.addEventListener("load", updateCode);

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead

const KEY_TAB = 9;
const KEY_ESC = 27;

textarea.onkeydown = (event) => {
  if (event.keyCode === KEY_TAB) {
    event.preventDefault();
    insertAtCaret("\t");
  }
  if (event.keyCode === KEY_ESC) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  const scrollPos = textarea.scrollTop;
  let caretPos = textarea.selectionStart;
  const front = textarea.value.substring(0, caretPos);
  const back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );

  textarea.value = front + text + back;
  caretPos += text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

// Update the saved userCode every time the user updates the text area code

textarea.onkeyup = () => {
  // We only want to save the state when the user code is being shown,
  // not the solution, so that solution is not saved over the user code
  if (solution.value === "Show solution") {
    userEntry = textarea.value;
  } else {
    solutionEntry = textarea.value;
  }
  updateCode();
};

测试你的技能!

¥Test your skills!

你已读完本文,但你还记得最重要的信息吗?在继续之前,你可以找到一些进一步的测试来验证你是否已保留此信息 - 请参阅 测试你的技能:数组

¥You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: Arrays.

结论

¥Conclusion

读完这篇文章后,我们相信你会同意数组看起来非常有用;你会看到它们在 JavaScript 中随处出现,通常与循环相关联,以便对数组中的每个项目执行相同的操作。我们将在下一个模块中教你有关循环的所有有用基础知识,但现在你应该给自己鼓掌并好好剩余一下;你已阅读本模块中的所有文章!

¥After reading through this article, we are sure you will agree that arrays seem pretty darn useful; you'll see them crop up everywhere in JavaScript, often in association with loops in order to do the same thing to every item in an array. We'll be teaching you all the useful basics there are to know about loops in the next module, but for now you should give yourself a clap and take a well-deserved break; you've worked through all the articles in this module!

剩下要做的唯一一件事就是完成本模块的评估,这将测试你对之前文章的理解。

¥The only thing left to do is work through this module's assessment, which will test your understanding of the articles that came before it.

也可以看看

¥See also

  • 索引集合 — 数组及其近亲类型数组的高级指南。
  • ArrayArray 对象参考页面 — 获取本页面讨论的功能的详细参考指南以及更多内容。