JavaScript中的数组创建

JavaScript中的数组创建

本文转载自:众成翻译
译者:loveky
链接:http://www.zcfy.cc/article/713
原文:http://rainsoft.io/power-up-the-array-creation-in-javascript/

数组是一个包含了对象或原始类型的有序集合。很难想象一个不使用数组的程序会是什么样。

以下是几种操作数组的方式:

  1. 初始化数组并设置初始值

  2. 通过索引访问数组元素

  3. 添加新元素

  4. 删除现有元素

本文涵盖了数组的初始化以及设置初始值的操作。在JavaScript中要做到这一点的基本方法是使用数组字面量,例如[1, 5, 8]或是数组构造器new Array (1, 5, 8)

除了手动枚举之外,JavaScript还提供了更有趣更直接的数组创建方式。让我一起看看在JavaScript中初始化数组的一般场景和高级场景吧。

1. 数组字面量

数组字面量由一组包裹在方括号[ ]之间的逗号分隔的元素element1, element2, ..., elementN组成。

让我们看几个数组字面量的例子:

在JS Bin中查看

let numbers = [1, 5, 7, 8];
let planets = ['Earth', 'Mercury', 'Jupiter'];

数组字面量可以包含任意类型的元素,包括null, undefined, 原始类型以及对象:

在JS Bin中查看

let mixed = [1, 'Earth', null, NaN, undefined, ['Mars']];

1.1 数组字面量中的逗号

逗号,用来分隔数组字面量中的元素。基于逗号的位置或是逗号之间元素的缺失的情况,不同结构的数组会被创建。

让我们详细看一看现有的三种情况。

第一种情况:普通的数组字面量

通常情况是在任何一对逗号之间都有一个元素并且数组字面量不以逗号开始或结尾。这是推荐的使用逗号分隔手动初始化数组的方式:

在JS Bin中查看

let items = ['first', 'second', 'third'];
items; // => ['first', 'second', 'third']

items是由2个逗号分隔的3个元素创建的。

在这个例子中item是一个密集数组,因为它的元素有着连续的索引(或者简单来说数组中没有空洞)。

大多数时候,你会使用这种方式初始化数组。

第二种情况: 在数组末尾的一个无用逗号

第二种情况和第一种情况类似,只不过在最后一个逗号之后没有指定元素。这种情况中,最后一个逗号会被JavaScript忽略:

在JS Bin中查看

let items = ['first', 'second', 'third', ];
items; // => ['first', 'second', 'third']

在元素'third'之后指定的一个逗号,它是数组中的最后一个逗号并且在那之后没有任何元素。这个末尾的逗号是无用的,意味着它对新创建的数组没有任何影响。

这种情况下JavaScript也会创建一个密集数组。

第三种情况: 逗号之间没有元素

第三种情况发生在当一对逗号之间没有指定元素或是数组字面量以一个逗号开始时。

这会创建一个稀疏数组:一个其元素索引不连续的集合(换句话说数组中存在空洞)。

下面的数组字面量以逗号开始,创建了一个稀疏数组:

在JS Bin中查看

let items = [, 'first', 'second', 'third'];
items;        // => [<1 empty slot>, 'first', 'second', 'third']
items[0];     // => undefined
items[1];     // => 'first'
items.length; // => 4

数组字面量[, ...]以逗号开始。结果是items是一个稀疏数组,在索引0的位置是一个空slot。访问空slot items[0]会得到undefined

区分一个空slot和一个值是undefined的元素是很重要的。通过索引访问这种类型的元素时都会得到undefined,这使得区分它们变得很棘手。

空slot意味着数组在某个索引位置上没有元素(index in array返回false),这与一个值是undefined的元素(index in array返回true)是不同的。

需要注意的是空slot在Firefox的控制台会被显示为<1 empty slot>,这是展示空slot的正确方法。Chrome的控制台会展示undefined x 1。其它浏览器的控制台只会简单的展示undefined

当数组字面量的两个逗号之间没有元素时也会创建一个稀疏数组:

在JS Bin中查看

let items = ['first', , 'second', 'third'];
items;        // => ['first', <1 empty slot> ,'second', 'third']
items[0];     // => 'first'
items[1];     // => undefined
items.length; // => 4

数组字面量包含了中间没有元素的逗号:[... , , ...]。这样item成了一个索引1处是一个空slot的稀疏数组。访问空slot items[1]会得到undefined

通常你应该避免这种会创建稀疏数组的使用方式。同时你也应该尽可能的不去操作稀疏数组。

在一个数组字面量中删除或是添加元素时你可能会在不经意间创建一个稀疏数组。因此在修改之后切记仔细检查。

1.2 spread运算符带来的改善

ECMAScript 6中引入的spread运算符改善了使用其它数组中的元素初始新数组这一操作。

在很多场景下spread运算符都可以使数组创建变得更简单。方法就是在数组字面量中把...作为源数组的前缀,然后源数组中的元素就被包括到新创建的数组中了。就这么简单。

下面的数组字面量在创建时使用了spread运算符:

在JS Bin中查看

let source = ['second', 'third'];
let items = ['first', ...source];
items; // => ['first', 'second', 'third']

数组字面量['First', ...source]表示'First'会被作为数组中的第一个元素。剩余的元素则是通过spread运算符从source数组取得。

常规的元素枚举方式可以和spread运算符可以不受限制的组合在一起。

在JS Bin中查看

let odds = [1, 3, 5];
let evens = [4, 6];
let zero = 0;
let negative = -1;
let items = [...odds, zero, ...evens, negative];
items; // => [1, 3, 5, 0, 4, 6, -1]

创建items时使用一个组合了普通变量zeronegative以及前置spread运算符的源数组...odds...evens的集合。

由于spread运算符接收的是普通的可迭代对象(数组默认就是可迭代的),这使得自定义的初始化成为可能。

一个生成器函数也会返回一个可迭代的生成器对象,因此你可以利用生成器的灵活性来创建数组。

让我们创建一个第一个参数代表元素值第二个参数代表元素数量的生成器函数。然后使用它和spread运算符以及数组字面量来初始化新数组:

在JS Bin中查看

function* elements(element, length) {let index = 0;while (length > index++) {yield element;}
}
[...elements(0, 5)];    // => [0, 0, 0, 0, 0]
[...elements('hi', 2)]; // => ['hi', 'hi']

每次执行elements(element, length)时都会创建一个生成器对象。spread运算符会利用该生成器对象来初始化数组。

[...elements(0, 5)]会创建一个有5个0的数组。而[...elements('hi', 2)]会创建一个有两个字符串'h1'的数组。

2. 数组构造器

JavaScript中的数组是一个对象。和任何对象一样,它有一个可以用来创建新实例的构造器函数Array。让我们看一个例子:

在JS Bin中查看

// 构造器调用
let arrayConstr = new Array(1, 5);
arrayConstr;                        // => [1, 5]
typeof arrayConstr;                 // => 'object'
arrayConstr.constructor === Array;  // => true
// 数组字面量
let arrayLiteral = [1, 5];
arrayLiteral;                       // => [1, 5]
typeof arrayLiteral;                // => 'object'
arrayLiteral.constructor === Array; // => true

arrayConstrarrayLiteral都是数组实例,它们的构造器都是Array。对象arrayConstr是通过构造器调用创建的:new Array(1, 5)

你也可以像调用普通函数那样通过Array来创建数组实例:Array(1, 5)

你应该更倾向于使用字面量[item1, item2, ..., itemN]而不是构造器new Array(item1, item2, ..., itemN)来创建数组。主要原因是数组字面量的写法更短,更简单。还有一个原因就是数组构造器在第一个参数是不同类型的值时,产生的怪异行为。

让我们看看Array使如何根据第一个参数的类型以及参数的个数来创建数组实例的吧。

2.1 数值类型的参数下创建稀疏数组

当数组构造器new Array(numberArg)以一个单一的数值类型的参数调用时,JavaScript会创建一个带有参数指定的个数的空slot的稀疏数组。

看一个例子:

在JS Bin中查看

let items = new Array(3);
items;        // => [<3 empty slots>]
items.length; // => 3

new Array(3)是一个带有单一参数3的构造器调用。一个长度为3的稀疏数组items被创建了,但实际上它并不包含任何元素而只是有几个空slot。

这种创建数组的方式本身并没有什么价值。然而把它和一些静态方法组合起来用于创建指定长度的数组并填充生成的元素时却是有用的。

2.2 枚举元素

如果调用Array构造器时传入了一个参数列表而不是单个数字,那么这些参数就会成为数组的元素。

这种方式和数组字面量的方式几乎一样,只不过是在一个构造器调用中而已。

下面的例子创建了一个数组:

let items = new Array('first', 'second', 'third');
items; // => ['first', 'second', 'third']

new Array('first', 'second', 'third')使用参数中的元素创建了一个数组。

由于spread运算符的灵活性,在构造器调用中使用来自其它数组的元素也是可行的:

在JS Bin中查看

let source = new Array('second', 'third');
let items = new Array('first', ...source);
items; // => ['first', 'second', 'third']

new Array('First', ...source)创建数组时使用了'First'元素以及source数组中的所有元素。

无论哪种方式,你都应该倾向于使用数组字面量,因为它更简单直接。

2.3 有用的静态方法

当读到关于通过在构造器调用中传入一个数字来创建稀疏数组的部分时你可能好奇这有什么实际的用处。

ECMAScript 6增加了一些有用的方法如Array.prototype.fill()Array.from()。这两个方法都可以用来填充一个稀疏数组中的空slot。

让我使用fill()方法来创建一个包含5个0的数组:

在JS Bin中查看

let zeros = new Array(5).fill(0);
zeros; // => [0, 0, 0, 0, 0]

new Array(5)创建了一个有5个空slot的稀疏数组。接着fill(0)方法用0填充了空slot。

静态方法Array.from()则有着更宽的使用场景。像上边的例子一样,让我们创建一个包含5个0的数组:

在JS Bin中查看

let zeros = Array.from(new Array(5), () => 0);
zeros; // => [0, 0, 0, 0, 0]

一个通过new Array(5)创建的长度为5的稀疏组数作为参数被传递给Array.from()。第二个参数作为一个返回0的映射函数。

共执行了5次迭代,每次迭代中箭头函数的返回值被用作数组的元素。

由于在每次迭代中都会执行映射函数,因此动态创建数组元素是可行的。让我们创建一个包含15的数组:

在JS Bin中查看

let items = Array.from(new Array(5), (item, index) => index + 1);
items; // => [1, 2, 3, 4, 5]

映射函数被调用时会传入两个参数:当前的item以及当前迭代的index。索引参数被用来生成元素:index + 1

Array.from()的第一个参数可以接受任何可迭代对象,这使得它更有价值。

让我们使用一个生成器对象创建一个递增的数字列表:

在JS Bin中查看

function* generate(max) {let count = 0;while (max > count++) {yield count;}
}
let items = Array.from(generate(5));
items;       // => [1, 2, 3, 4, 5]
let itemsSpread = [...generate(5)];
itemsSpread; // => [1, 2, 3, 4, 5]

generate(max)是一个生成器函数,它会生成从一串从1max的数字。

Array.from(generate(5))使用一个生成器对象作为参数创建了一个包含15数字的数组。

使用spread运算符[...generate(5)]和数组字面量可以达到同样的目的。

3. 总结

数组初始化是操作集合时的常见操作。JavaScript提供了多种方法以及灵活性来实现该目的。

数组构造器的行为在很多情况下会让你感到意外。因此数组字面量是初始化数组实例更好,更简单的方式。

当数组需要根据基于每个迭代元素的计算进行初始化时,Array.from()是一个不错的选择。

如果数组元素需要被填充为同一个值,使用Array.prototype.fill()new Array(length)的组合。

不要低估可迭代对象和生成器函数的能力,它们可以和spread运算符组合起来使用在数组字面量或是Array.from()中。

转载于:https://www.cnblogs.com/wwhhq/p/8079102.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CODEVS——T1519 过路费

http://codevs.cn/problem/1519/ 时间限制: 1 s空间限制: 256000 KB题目等级 : 大师 Master题解查看运行结果题目描述 Description在某个遥远的国家里,有 n个城市。编号为 1,2,3,…,n。这个国家的政府修建了m 条双向道路,每条道路连接着两个城市。政府规…

pca数学推导_PCA背后的统计和数学概念

pca数学推导As I promised in the previous article, Principal Component Analysis (PCA) with Scikit-learn, today, I’ll discuss the mathematics behind the principal component analysis by manually executing the algorithm using the powerful numpy and pandas lib…

pandas之cut

cut( )用来把一组数据分割成离散的区间。 cut(x, bins, rightTrue, labelsNone, retbinsFalse, precision3, include_lowestFalse, duplicatesraise) # x:被切分的数据,必须是一维的 # bins:①int型整数:将x按照数值大小平均分成分…

为Tueri.io构建React图像优化组件

Let’s face it, image optimization is hard. We want to make it effortless.面对现实吧,图像优化非常困难。 我们希望毫不费力。 When we set out to build our React Component there were a few problems we wanted to solve:当我们开始构建React组件时&#…

红黑树分析

红黑树的性质: 性质1:每个节点要么是黑色,要么是红色。 性质2:根节点是黑色。性质3:每个叶子节点(NIL)是黑色。性质4:每个红色节点的两个子节点一定都是黑色。不能有两个红色节点相…

overlay 如何实现跨主机通信?- 每天5分钟玩转 Docker 容器技术(52)

上一节我们在 host1 中运行了容器 bbox1,今天将详细讨论 overlay 网络跨主机通信的原理。 在 host2 中运行容器 bbox2: bbox2 IP 为 10.0.0.3,可以直接 ping bbox1: 可见 overlay 网络中的容器可以直接通信,同时 docke…

第 132 章 Example

这里介绍一个负载均衡放置问题,我们可以把它摆放在任何位置,每种方案都各有优缺点,需要根据你的实际情况选择使用 适用于HAProxy / Nginx / LVS 等等 这里用web,db为例子,讲述负载均衡之间的关系 132.1. 双负载均衡的用法 User --…

Python:实现图片裁剪的两种方式——Pillow和OpenCV

原文:https://blog.csdn.net/hfutdog/article/details/82351549 在这篇文章里我们聊一下Python实现图片裁剪的两种方式,一种利用了Pillow,还有一种利用了OpenCV。两种方式都需要简单的几行代码,这可能也就是现在Python那么流行的原…

第一个应在JavaScript数组的最后

by Thomas Barrasso由Thomas Barrasso 第一个应在JavaScript数组的最后 (The first shall be last with JavaScript arrays) So the last shall be [0], and the first [length — 1].所以最后一个应该是[0] ,第一个[length_1]。 – Adapted from Matthew 20:16–根…

鼠标移动到ul图片会摆动_我们可以从摆动时序分析中学到的三件事

鼠标移动到ul图片会摆动An opportunity for a new kind of analysis of Major League Baseball data may be upon us soon. Here’s how we can prepare.不久之后,我们将有机会对美国职棒大联盟数据进行新的分析。 这是我们准备的方法。 It is tempting to think t…

leetcode 1052. 爱生气的书店老板(滑动窗口)

今天,书店老板有一家店打算试营业 customers.length 分钟。每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开。 在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气&#xf…

回到网易后开源APM技术选型与实战

篇幅一:APM基础篇\\1、什么是APM?\\APM,全称:Application Performance Management ,目前市面的系统基本都是参考Google的Dapper(大规模分布式系统的跟踪系统)来做的,翻译传送门《google的Dappe…

持续集成持续部署持续交付_如何开始进行持续集成

持续集成持续部署持续交付Everything you need to know to get started with continuous integration: branching strategies, tests automation, tools and best practices.开始进行持续集成所需的一切:分支策略,测试自动化,工具和最佳实践。…

51nod 1073约瑟夫环

思路传送门 &#xff1a;http://blog.csdn.net/kk303/article/details/9629329 n里面挑选m个 可以递推从n-1里面挑m个 然后n-1里面的x 可以转换成 n里面的x 的公式 x &#xff08;xm&#xff09;%n; #include <bits/stdc.h> using namespace std;int main () {int n,m;s…

如何选择优化算法遗传算法_用遗传算法优化垃圾收集策略

如何选择优化算法遗传算法Genetic Algorithms are a family of optimisation techniques that loosely resemble evolutionary processes in nature. It may be a crude analogy, but if you squint your eyes, Darwin’s Natural Selection does roughly resemble an optimisa…

robot:截图关键字

参考&#xff1a; https://www.cnblogs.com/hong-fithing/p/9656221.html--python https://blog.csdn.net/weixin_43156282/article/details/87350309--robot https://blog.csdn.net/xiongzaiabc/article/details/82912280--截图指定区域 转载于:https://www.cnblogs.com/gcgc/…

leetcode 832. 翻转图像

给定一个二进制矩阵 A&#xff0c;我们想先水平翻转图像&#xff0c;然后反转图像并返回结果。 水平翻转图片就是将图片的每一行都进行翻转&#xff0c;即逆序。例如&#xff0c;水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。 反转图片的意思是图片中的 0 全部被 1 替换&#xff…

SVN服务备份操作步骤

SVN服务备份操作步骤1、准备源服务器和目标服务器源服务器&#xff1a;192.168.1.250目标服务器&#xff1a;192.168.1.251 root/rootroot 2、对目标服务器&#xff08;251&#xff09;装SVN服务器&#xff0c; 脚本如下&#xff1a;yum install subversion 3、创建一个新的仓库…

SpringCloud入门(一)

1. 系统架构演变概述 #mermaid-svg-F8dvnEDl6rEgSP97 .label{font-family:trebuchet ms, verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-F8dvnEDl6rEgSP97 .label text{fill:#333}#mermaid-svg-F8dvnEDl6rEgSP97 .node rect,#merm…

PullToRefreshListView中嵌套ViewPager滑动冲突的解决

PullToRefreshListView中嵌套ViewPager滑动冲突的解决 最近恰好遇到PullToRefreshListView中需要嵌套ViewPager的情况,ViewPager 作为头部添加到ListView中&#xff0c;发先ViewPager在滑动过程中流畅性太差几乎很难左右滑动。在网上也看了很多大神的介绍&#xff0c;看了ViewP…