在本模块的最后一篇文章中, 我们将看看数组——一种将一组数据存储在单个变量名下的优雅方式。 现在我们看看为什么这是有用的,然后探索如何来创建一个数组,检索、添加和删除存储在数组中的项目,以及更多方式。
前提: | 基本的电脑知识,对HTML、CSS语法有基础的理解,能理解什么是JavaScript。 |
---|---|
目的: | 理解什么是数组,和如何在JavaScript中操作数组。 |
什么是一个数组?
数组通常被描述为“列表样对象”; 它们基本上是包含存储在列表中的多个值的单个对象。 数组对象可以存储在变量中并以与其他任何类型的值完全相同的方式处理,区别在于我们可以单独访问列表中的每个值,并使用列表执行超级有用和高效的操作,如循环 它对每个价值都做同样的事情。 也许我们有一系列产品和价格存储在一个阵列中,我们想循环遍历所有这些产品,并将它们打印在发票上,同时将所有的价格合在一起并打印底部的总价格。
如果我们没有数组,我们必须将每个项目存储在一个单独的变量中,然后调用打印的代码,并为每个项目单独添加。 写出来的时间要长得多,效率更低,容易出错。 如果我们有10个项目添加到发票,这将是不够的,但是100项,或1000? 我们稍后将在文章中回到这个例子。
像以前的文章一样,我们通过在JavaScript控制台中输入一些示例来了解数组的真正基础知识。 我们在下面提供了一个(您也可以在单独的选项卡或窗口中打开此控制台,或者如果您愿意,请使用浏览器开发者控制台)。
Hidden code
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JavaScript console</title> <style> * { box-sizing: border-box; } html { background-color: #0C323D; color: #809089; font-family: monospace; } body { max-width: 700px; } p { margin: 0; width: 1%; padding: 0 1%; font-size: 16px; line-height: 1.5; float: left; } .input p { margin-right: 1%; } .output p { width: 100%; } .input input { width: 96%; float: left; border: none; font-size: 16px; line-height: 1.5; font-family: monospace; padding: 0; background: #0C323D; color: #809089; } div { clear: both; } </style> </head> <body> </body> <script> var geval = eval; function createInput() { var inputDiv = document.createElement('div'); var inputPara = document.createElement('p'); var inputForm = document.createElement('input'); inputDiv.setAttribute('class','input'); inputPara.textContent = '>'; inputDiv.appendChild(inputPara); inputDiv.appendChild(inputForm); document.body.appendChild(inputDiv); if(document.querySelectorAll('div').length > 1) { inputForm.focus(); } inputForm.addEventListener('change', executeCode); } function executeCode(e) { try { var result = geval(e.target.value); } catch(e) { var result = 'error — ' + e.message; } var outputDiv = document.createElement('div'); var outputPara = document.createElement('p'); outputDiv.setAttribute('class','output'); outputPara.textContent = 'Result: ' + result; outputDiv.appendChild(outputPara); document.body.appendChild(outputDiv); e.target.disabled = true; e.target.parentNode.style.opacity = '0.5'; createInput() } createInput(); </script> </html>
创建数组
数组由方括号构成,其中包含用逗号分隔的项目列表。
- 假设我们想在一个数组中存储一个购物清单 - 我们会做一些如下所示的事情。 在您的控制台中输入以下行:
var shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles']; shopping;
- 在这种情况下,数组中的每个项目都是一个字符串,但请记住,您可以将数组中的任何项目存储在数组中 - 字符串,数字,对象,另一个变量,甚至另一个数组。 您也可以混合和匹配项目类型 - 它们并不都是数字,字符串等。尝试这些:
var sequence = [1, 1, 2, 3, 5, 8, 13]; var random = ['tree', 795, [0, 1, 2]];
- 尝试创建您自己的几个数组,然后再继续。
访问和修改数组项
然后,您可以使用括号表示法访问数组中的各个项目,方式与访问字符串中的字母相同。
- 在您的控制台中输入以下内容:
shopping[0]; // returns "bread"
- 您还可以通过简单地向单个数组项提供新值来修改数组中的项目。 尝试这个:
shopping[0] = 'tahini'; shopping; // shopping will now return [ "tahini", "milk", "cheese", "hummus", "noodles" ]
Note: 我们以前说过,但是提醒一下 - 电脑从0开始计数! - 请注意,数组中的数组称为多维数组。 您可以通过将两组方括号链接在一起来访问数组内的另一个数组。 例如,要访问数组中的一个作为随机数组内的第三个项目的内容(见上一节),我们可以这样做:
random[2][2];
- 在继续前进之前,再尝试一下,并对数组示例进行更多修改。
查找数组长度
你可以通过使用length
的字符串长度(以字符为单位)找出数组的长度(它中有多少项)属性。 尝试以下:
sequence.length; // should return 7
这有其他用途,但最常用来告诉循环,直到它循环遍历数组中的所有项。 所以例如:
var sequence = [1, 1, 2, 3, 5, 8, 13]; for (var i = 0; i < sequence.length; i++) { console.log(sequence[i]); }
您将在以后的文章中正确地了解循环,但简要地说,这段代码说:
- 在数组中的项目编号0开始循环。
- 停止在项目编号等于数组长度的循环。 这将适用于任何长度的数组,但在这种情况下,它将停止在项目编号7的循环(这是好的,因为最后一个项目 - 我们希望循环覆盖 - 是6。
- 对于每个项目,使用console.log()将其打印到浏览器控制台。
一些有用的数组方法
在本节中,我们将介绍一些相当有用的数组相关方法,这些方法允许我们将字符串拆分为数组项,反之亦然,并将新项添加到数组中。
字符串和数组之间的转换
通常,您会看到一个包含在一个长长的字符串中的原始数据,您可能希望将有用的项目分成更有用的表单,然后对它们进行处理,例如将它们显示在数据表中。 为此,我们可以使用split()
方法。 在其最简单的形式中,这需要一个参数,您要将字符串分隔的字符,并返回分隔符之间的子串,作为数组中的项。
Note: 好的,这在技术上是一个字符串方法,而不是一个数组方法,但是我们把它放在数组中,因为它在这里很好。
- 我们来玩这个,看看它是如何工作的。 首先,在控制台中创建一个字符串:
var myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';
- 现在我们用每个逗号分隔它:
var myArray = myData.split(','); myArray;
- 最后,尝试找到新数组的长度,并从中检索一些项目:
myArray.length; myArray[0]; // the first item in the array myArray[1]; // the second item in the array myArray[myArray.length-1]; // the last item in the array
- 您也可以使用
join()
方法进行相反的操作。 尝试以下:var myNewString = myArray.join(','); myNewString;
- 将数组转换为字符串的另一种方法是使用
toString()
方法。 toString()可以比join()更简单,因为它不需要一个参数,但更有限制。 使用join()可以指定不同的分隔符(尝试使用与逗号不同的字符运行步骤4)。var dogNames = ["Rocket","Flash","Bella","Slugger"]; dogNames.toString(); //Rocket,Flash,Bella,Slugger
添加和删除数组项
我们还没有涵盖添加和删除数组项目 - 现在让我们来看看。 我们将在上一节中使用我们最后提到的myArray数组。 如果您尚未遵循该部分,请先在控制台中创建数组:
var myArray = ['Manchester', 'London', 'Liverpool', 'Birmingham', 'Leeds', 'Carlisle'];
首先,要在数组末尾添加或删除一个项目,我们可以使用push()
和pop()
。
- 让我们先使用push() - 注意,你需要添加一个或多个要添加到数组末尾的项目。 尝试这个:
myArray.push('Cardiff'); myArray; myArray.push('Bradford', 'Brighton'); myArray;
- 当方法调用完成时,将返回数组的新长度。 如果要将新数组长度存储在变量中,可以执行以下操作:
var newLength = myArray.push('Bristol'); myArray; newLength;
- 从数组中删除最后一个项目就像在其上运行pop()一样简单。 尝试这个:
myArray.pop();
- 当方法调用完成时,将返回已删除的项目。 你也可以这样做:
var removedItem = myArray.pop(); myArray; removedItem;
unshift()
和shift()
方式,除了它们在数组的开头工作,而不是结束。
首先unshift()
— 尝试一下命令myArray.unshift('Edinburgh'); myArray;
- 现在shift(); 尝试这些!
var removedItem = myArray.shift(); myArray; removedItem;
积极学习:打印这些产品
我们回到前面描述的例子 - 打印出发票上的产品名称和价格,然后总结价格并将其印在底部。 在下面的可编辑示例中,包含数字的注释 - 每个标记都是您必须向代码添加内容的地方。 它们如下:
- //号码1注释下面是一些字符串,每个字符串包含一个产品名称和一个冒号分隔的冒号。 我们希望您将其转换为数组,并将其存储在名为products的数组中。
- 与//号2注释相同的行是for循环的开头。 在这行中,我们目前有i <= 0,这是一个条件测试,导致for循环立即停止,因为它说“当我不再小于或等于0”时停止,我从0开始。 我们希望您使用条件测试来替换它,当我不再小于产品数组的长度时,该条件测试会停止循环。
- 就在第3号注释的下方,我们希望您编写一行代码,将当前数组项(名称:price)分成两个独立的项目,一个只包含该名称,一个只包含该价格。 如果您不确定如何执行此操作,请参阅有用的字符串方法文章以获得一些帮助,甚至更好的看看本文中的转换字符串和数组部分。
- 作为上述代码行的一部分,您还需要将价格从字符串转换为数字。 如果你不记得如何做,请查看第一个字符串文章。
- 有一个名为total的变量被创建,并在代码的顶部赋值为0。 在循环内(在第4号下面),我们希望你添加一个行,将当前项目价格添加到循环的每个迭代中的总数,以便在代码结尾处将正确的总数打印到发票上。 您可能需要一个赋值运算符来执行此操作。
- 我们希望您改变第5行以下的行,以便使itemText变量等于“当前项目名称 - $ current item price”,例如“Shoes - $ 23.99”,因此每个 项目打印在发票上。 这只是简单的字符串连接,这应该是你熟悉的。
Playable code
<div class="output" style="min-height: 150px;"> <ul> </ul> <p></p> </div> <textarea id="code" class="playable-code" style="height: 370px;"> var list = document.querySelector('.output ul'); var totalBox = document.querySelector('.output p'); var total = 0; list.innerHTML = ''; totalBox.textContent = ''; // number 1 'Underpants:6.99' 'Socks:5.99' 'T-shirt:14.99' 'Trousers:31.99' 'Shoes:23.99'; for (var i = 0; i <= 0; i++) { // number 2 // number 3 // number 4 // number 5 itemText = 0; var listItem = document.createElement('li'); listItem.textContent = itemText; list.appendChild(listItem); } 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>
var textarea = document.getElementById('code'); var reset = document.getElementById('reset'); var solution = document.getElementById('solution'); var code = textarea.value; function updateCode() { eval(textarea.value); } reset.addEventListener('click', function() { textarea.value = code; updateCode(); }); solution.addEventListener('click', function() { textarea.value = jsSolution; updateCode(); }); var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar totalBox = document.querySelector(\'.output p\');\nvar total = 0;\nlist.innerHTML = \'\';\ntotalBox.textContent = \'\';\n\nvar products = [\'Underpants:6.99\',\n \'Socks:5.99\',\n \'T-shirt:14.99\',\n \'Trousers:31.99\',\n \'Shoes:23.99\'];\n\nfor(var i = 0; i < products.length; i++) {\n var subArray = products[i].split(\':\');\n var name = subArray[0];\n var price = Number(subArray[1]);\n total += price;\n itemText = name + \' — $\' + price;\n\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = \'Total: $\' + total.toFixed(2);'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode);
积极学习:前5大搜索
对于push()
和pop()
当您在网络应用程序中维护当前活动项目的记录时。 例如,在动画场景中,您可能会有一系列表示当前显示的背景图形的对象,并且由于性能或混乱原因,您可能只需要一次显示50个。 当创建新对象并将其添加到数组中时,可以从数组中删除较旧的对象以维护所需的数字。
在这个例子中,我们将展示一个更简单的使用 - 在这里我们给你一个假的搜索网站,一个搜索框。 这个想法是,当在搜索框中输入条款时,列表中会显示前5个先前的搜索字词。 当术语数量超过5时,每当新术语被添加到顶部时,最后一个术语开始被删除,因此总是显示5个以前的术语。
Note: 在真正的搜索应用中,您可能可以点击先前的搜索字词返回上一次搜索,并显示实际的搜索结果! 我们现在只是保持简单。
要完成该应用程序,我们需要您:
- 在//数字1注释下面添加一行,将输入到搜索输入中的当前值添加到数组的开头。 这可以使用searchInput.value检索。
- 在// number 2注释下方添加一行,该行删除数组末尾的当前值。
Playable code 2
<div class="output" style="min-height: 150px;"> <input type="text"><button>Search</button> <ul> </ul> </div> <textarea id="code" class="playable-code" style="height: 370px;"> var list = document.querySelector('.output ul'); var searchInput = document.querySelector('.output input'); var searchBtn = document.querySelector('.output button'); list.innerHTML = ''; var myHistory = []; searchBtn.onclick = function() { // 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 (var i = 0; i < myHistory.length; i++) { itemText = myHistory[i]; var 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 >= 5) { // 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>
var textarea = document.getElementById('code'); var reset = document.getElementById('reset'); var solution = document.getElementById('solution'); var code = textarea.value; function updateCode() { eval(textarea.value); } reset.addEventListener('click', function() { textarea.value = code; updateCode(); }); solution.addEventListener('click', function() { textarea.value = jsSolution; updateCode(); }); var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar searchInput = document.querySelector(\'.output input\');\nvar searchBtn = document.querySelector(\'.output button\');\n\nlist.innerHTML = \'\';\n\nvar myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== \'\') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = \'\';\n\n for(var i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = \'\';\n searchInput.focus();\n }\n}'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode);
总结
阅读本文后,我们相信您会同意数组看起来很有用; 你会看到它们在JavaScript中随处可见,通常与循环相关联,以便对数组中的每个项目做同样的事情。 我们将教你所有有用的基础知识,了解下一个模块中的循环,但现在你应该给自己一个鼓掌,并应得当之无愧的休息; 您已经完成了本单元中的所有文章!
唯一需要做的就是通过这个模块的评估,这将测试你对之前的文章的理解。
也可以看看
- Indexed collections — 数组及其表兄弟类型阵列的高级指导。
Array
— Array对象引用页面 - 有关此页面中讨论的功能的详细参考指南等等。