JavaScript中的数组创建
JavaScript中的数组创建
数组是一个包含了对象或原始类型的有序集合。很难想象一个不使用数组的程序会是什么样。
以下是几种操作数组的方式:
初始化数组并设置初始值
通过索引访问数组元素
添加新元素
删除现有元素
本文涵盖了数组的初始化以及设置初始值的操作。在JavaScript中要做到这一点的基本方法是使用数组字面量,例如[1, 5, 8]
或是数组构造器new Array (1, 5, 8)
。
除了手动枚举之外,JavaScript还提供了更有趣更直接的数组创建方式。让我一起看看在JavaScript中初始化数组的一般场景和高级场景吧。
1. 数组字面量
数组字面量由一组包裹在方括号[
]
之间的逗号分隔的元素element1, element2, ..., elementN
组成。
让我们看几个数组字面量的例子:
let numbers = [1, 5, 7, 8];
let planets = ['Earth', 'Mercury', 'Jupiter'];
数组字面量可以包含任意类型的元素,包括null
, undefined
, 原始类型以及对象:
let mixed = [1, 'Earth', null, NaN, undefined, ['Mars']];
1.1 数组字面量中的逗号
逗号,
用来分隔数组字面量中的元素。基于逗号的位置或是逗号之间元素的缺失的情况,不同结构的数组会被创建。
让我们详细看一看现有的三种情况。
第一种情况:普通的数组字面量
通常情况是在任何一对逗号之间都有一个元素并且数组字面量不以逗号开始或结尾。这是推荐的使用逗号分隔手动初始化数组的方式:
let items = ['first', 'second', 'third'];
items; // => ['first', 'second', 'third']
items
是由2个逗号分隔的3个元素创建的。
在这个例子中item
是一个密集数组,因为它的元素有着连续的索引(或者简单来说数组中没有空洞)。
大多数时候,你会使用这种方式初始化数组。
第二种情况: 在数组末尾的一个无用逗号
第二种情况和第一种情况类似,只不过在最后一个逗号之后没有指定元素。这种情况中,最后一个逗号会被JavaScript忽略:
let items = ['first', 'second', 'third', ];
items; // => ['first', 'second', 'third']
在元素'third'
之后指定的一个逗号,它是数组中的最后一个逗号并且在那之后没有任何元素。这个末尾的逗号是无用的,意味着它对新创建的数组没有任何影响。
这种情况下JavaScript也会创建一个密集数组。
第三种情况: 逗号之间没有元素
第三种情况发生在当一对逗号之间没有指定元素或是数组字面量以一个逗号开始时。
这会创建一个稀疏数组:一个其元素索引不连续的集合(换句话说数组中存在空洞)。
下面的数组字面量以逗号开始,创建了一个稀疏数组:
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
。
当数组字面量的两个逗号之间没有元素时也会创建一个稀疏数组:
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运算符:
let source = ['second', 'third'];
let items = ['first', ...source];
items; // => ['first', 'second', 'third']
数组字面量['First', ...source]
表示'First'
会被作为数组中的第一个元素。剩余的元素则是通过spread运算符从source
数组取得。
常规的元素枚举方式可以和spread运算符可以不受限制的组合在一起。
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
时使用一个组合了普通变量zero
和negative
以及前置spread运算符的源数组...odds
和...evens
的集合。
由于spread运算符接收的是普通的可迭代对象(数组默认就是可迭代的),这使得自定义的初始化成为可能。
一个生成器函数也会返回一个可迭代的生成器对象,因此你可以利用生成器的灵活性来创建数组。
让我们创建一个第一个参数代表元素值第二个参数代表元素数量的生成器函数。然后使用它和spread运算符以及数组字面量来初始化新数组:
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
。让我们看一个例子:
// 构造器调用
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
arrayConstr
和arrayLiteral
都是数组实例,它们的构造器都是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的稀疏数组。
看一个例子:
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运算符的灵活性,在构造器调用中使用来自其它数组的元素也是可行的:
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的数组:
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的数组:
let zeros = Array.from(new Array(5), () => 0);
zeros; // => [0, 0, 0, 0, 0]
一个通过new Array(5)
创建的长度为5
的稀疏组数作为参数被传递给Array.from()
。第二个参数作为一个返回0
的映射函数。
共执行了5
次迭代,每次迭代中箭头函数的返回值被用作数组的元素。
由于在每次迭代中都会执行映射函数,因此动态创建数组元素是可行的。让我们创建一个包含1
到5
的数组:
let items = Array.from(new Array(5), (item, index) => index + 1);
items; // => [1, 2, 3, 4, 5]
映射函数被调用时会传入两个参数:当前的item
以及当前迭代的index
。索引参数被用来生成元素:index + 1
。
Array.from()
的第一个参数可以接受任何可迭代对象,这使得它更有价值。
让我们使用一个生成器对象创建一个递增的数字列表:
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)
是一个生成器函数,它会生成从一串从1
到max
的数字。
Array.from(generate(5))
使用一个生成器对象作为参数创建了一个包含1
到5
数字的数组。
使用spread运算符[...generate(5)]
和数组字面量可以达到同样的目的。
3. 总结
数组初始化是操作集合时的常见操作。JavaScript提供了多种方法以及灵活性来实现该目的。
数组构造器的行为在很多情况下会让你感到意外。因此数组字面量是初始化数组实例更好,更简单的方式。
当数组需要根据基于每个迭代元素的计算进行初始化时,Array.from()
是一个不错的选择。
如果数组元素需要被填充为同一个值,使用Array.prototype.fill()
和new Array(length)
的组合。
不要低估可迭代对象和生成器函数的能力,它们可以和spread运算符组合起来使用在数组字面量或是Array.from()
中。
本文转载自:众成翻译
译者:loveky
链接:http://www.zcfy.cc/article/713
原文:http://rainsoft.io/power-up-the-array-creation-in-javascript/
JavaScript中的数组创建的更多相关文章
- 前端开发:Javascript中的数组,常用方法解析
前端开发:Javascript中的数组,常用方法解析 前言 Array是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array ...
- javascript中的数组扩展(一)
javascript中的数组扩展(一) 随着学习的深入,发现需要学习的关于数组的内容也越来越多,后面将会慢慢归纳,有的是对前面的强化,有些则是关于前面的补充. 一.数组的本质 数组是按照次序排 ...
- JavaScript中的数组详解
JavaScript中的数组 一.数组的定义 数组是值的有序集合,或者说数组都是数据的有序列表. 二.创建数组 [字面量形式] 1.空数组 var arr=[]; 2.带有元素的数组 var arr= ...
- JavaScript中对数组和数组API的认识
JavaScript中对数组和数组API的认识 一.数组概念: 数组是JavaScript中的一类特殊的对象,用一对中括号“[]”表示,用来在单个的变量中存储多个值.在数组中,每个值都有一个对应的不重 ...
- JavaScript中的数组和字符串
知识内容: 1.JavaScript中的数组 2.JavaScript中的字符串 一.JavaScript中的数组 1.JavaScript中的数组是什么 数组指的是数据的有序列表,每种语言基本上都有 ...
- javascript中稀疏数组和密集数组
密集数组 数组是一片连续的存储空间,有着固定的长度.加入数组其实位置是address,长度为n,那么占用的存储空间是address[0],address[1],address[2].......add ...
- Javascript中判断数组的正确姿势
在 Javascript 中,如何判断一个变量是否是数组? 最好的方式是用 ES5 提供的 Array.isArray() 方法(毕竟原生的才是最屌的): var a = [0, 1, 2]; con ...
- JavaScript中对数组的操作
原文:JavaScript中对数组的操作 一:数组的使用 1.定义:JavaScript中对数组的定义有两种形式.如: .var arr = [12,3,5,8]; .var arr = new Ar ...
- JavaScript中一个对象数组按照另一个数组排序
JavaScript中一个对象数组按照另一个数组排序 需求:排序 const arr1 = [33, 11, 55, 22, 66]; const arr2 = [{age: 55}, {age: 2 ...
随机推荐
- 团体程序设计天梯赛-练习集-L1-048. 矩阵A乘以B
L1-048. 矩阵A乘以B 给定两个矩阵A和B,要求你计算它们的乘积矩阵AB.需要注意的是,只有规模匹配的矩阵才可以相乘.即若A有Ra行.Ca列,B有Rb行.Cb列,则只有Ca与Rb相等时,两个矩阵 ...
- BZOJ 1740: [Usaco2005 mar]Yogurt factory 奶酪工厂 贪心 + 问题转化
Description The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. Over the ...
- js中的数组遍历
js中的数组遍历是项目中经常用到的,在这里将几种方法做个对比. ! for循环:使用评率最高,也是最基本的一种遍历方式. let arr = ['a','b','c','d','e']; for (l ...
- jQuery升级踩坑之路
1.使用了被废弃的jQuery.browser属性 jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support . 在更 ...
- git常见问题总结
1.每次上传文件的时候,有很多iml文件容易不小心上传上去,然后报错,所以可以把这些文件取消上传 如图所示,每次提交时,都不会显示标红文件 具体操作步骤如下:
- PHP学习总结(14)——PHP入门篇之常用运算符
一.什么是运算符 什么是运算符?运算符是告诉PHP做相关运算的标识符号.例如,你需要计算123乘以456等于多少,这时候就需要一个符号,告诉服务器,你需要做乘法运算. PHP中的运算符有哪些?PHP运 ...
- snmptrap、snmpinform和snmptrapd的详细介绍及其用法
http://blog.csdn.net/reille/article/details/8712087
- COGS——C1176. [郑州101中学] 月考
http://cogs.pro/cogs/problem/problem.php?pid=1176 [题目描述] 在上次的月考中Bugall同学违反了考场纪律还吃了处分,更可气的是在第二天的校会时 间 ...
- POJ 3130
这题,加了精度错了,不加精度反而对了... #include <iostream> #include <cstdio> #include <cstring> #in ...
- Android自己定义控件之轮播图控件
背景 近期要做一个轮播图的效果.网上看了几篇文章.基本上都能找到实现,效果还挺不错,可是在写的时候感觉每次都要单独去又一次在Activity里写一堆代码.于是自己封装了一下.这里仅仅是做了下封装成一个 ...