已编入索引的集合

编入索引的集合是一种数据结构,其中存储元素并 使用编号索引进行访问。存储在编入索引的集合中的值 分配从 0 开始的编号索引,这是一种称为“零索引”的模式。 然后,您可以通过引用 索引

数组

数组是一种容器,可以包含零个或多个任意数据类型的值, 包括复杂对象或其他数组。存储在数组中的值 有时称为“元素”数组的值。

创建数组

与原始数据类型一样,创建数组的方法有两种:如 数组字面量,或者调用 JavaScript 的内置 Array() 构造函数 和new Array()。为变量分配数组可提供高度可移植性 和可迭代方式来分配 为单个标识符指定多个值。

数组字面量语法使用一对括号 ([]),将零个或多个值括起来 逗号分隔数据值:

const myArray = [];

数组构造函数语法使用 JavaScript 的内置 Array 对象作为 包含 new 关键字的构造函数:

const myArray = new Array();

数组字面量和数组构造函数语法都允许您使用 但其语法与 值。数组字面量语法在 括号,其外观与生成的数组相同:

const myArray = [ true, null, "String", false ];

myArray;
> [ true, null, "String", false ]

数组构造函数语法将逗号分隔值作为参数,其中 特殊行为异常:

const myArray = new Array( true, null, "String", false );

myArray;
> Array(4) [ true, null, "String", false ]

将单个数值传递给 Array 构造函数时,该值 未分配到结果数组中的第 0 个位置。而是使用数组 使用该数量的空槽创建值。这并不会强加 数组的限制。可以通过同样的方式在文件夹中添加和移除项 与数组字面量一样。

// Firefox:\
const myArray = new Array( 10 );

myArray;
> Array(10) [ <10 empty slots> ]
// Chrome:
const myArray = new Array( 10 );

myArray;
> (10) [empty × 10]

包含空槽位的数组(有时称为“稀疏数组”)是特殊数组 案例为空,而不是包含 undefined 或显式 null 值 slot 经常(但并不总是)被视为 undefined 值 语言。

您可能会不小心使用数组字面量语法创建稀疏数组,方法是 创建数组字面量时省略逗号之间的值:

const myArray = [ true,, true, false ];

myArray;
> Array(4) [ true, <1 empty slot>, true, false ]

尽管空槽位并非在所有上下文中都被视为有意义的值, 会计入数组的总长度,因此可能会导致 遍历时出现意料之外的结果 数组的值:

const myArray = [ 1,, 3, 4 ];

myArray.length;
> 4

for( const myValue of myArray ) {
  console.log( myValue + 10 );
}
> 11
> NaN
> 13
> 14

这是 JavaScript 最早的设计决策的一个阻碍。 避免在现代开发中使用稀疏数组。

与基元一样,数组字面量 从相应构造函数继承属性和方法。 由于数组是一种特殊形式的对象,因此数组字面量语法和 new Array() 语法创建功能完全相同的结果: 会从 Array 构造函数继承其原型。

const arrayLiteral = [];
const arrayConstructor = new Array();

typeof arrayLiteral;
> "object"

arrayLiteral;
> Array []
    length: 0
    <prototype>: Array []

typeof arrayConstructor;
> "object"

arrayConstructor;
> Array []
    length: 0
    <prototype>: Array []

因为两个结果完全相同,并且数组字面量语法更简洁 和字面量,因此我们强烈建议始终使用数组字面量语法, new Array() 语法。

访问数组值

您可以使用括号表示法(即 一对括号 ([]),紧跟在包含 编号:


[ "My string", "My other string" ][ 1 ];
> "My other string"

const myArray = [ "My string", 50, true ];

myArray[ 0 ];
> "My string"

myArray[ 1 ];
> 50

myArray[ 2 ];
> true

JavaScript 中的数组不关联, 这意味着您不能使用任意字符串作为索引。不过,数字 用于访问数组中元素的值被强制转换为后面的字符串值 场景,这意味着您可以使用仅包含数字值的字符串值, 字符:

const myArray = [ "My string", 50, true ];

myArray[ 2 ];
> true

myArray[ "2" ];
> true

尝试访问数组中定义的元素之外的元素会导致 undefined,而不是错误:

const myArray = [ "My string", 50, true ];

myArray[ 9 ];
> undefined

解构分配

解构赋值是从 数组或对象,并将其分配到 这个过程有时称为“解包”原始数据结构, 但不会修改原始数组或对象。

解构赋值使用一个数组或对象的类标识符列表来 可帮助您跟踪价值最简单的方法就是称为“绑定模式” 解构时,每个值都会从数组或对象中解封,并分配给 相应的变量,使用 letconst(或 var)进行初始化:

const myArray = [ "A string", "A second string" ];
const [ myFirstElement, mySecondElement ] = myArray;

const myObject = { firstValue: false, secondValue: true };
const { myProp, mySecondProp } = myObject;

myFirstElement;
> "My string"

mySecondElement;
> "Second string"

myProp;
> false

mySecondProp;
> true

大括号 ({}) 用于解构对象,方括号 ([]) 用于解构对象 解构数组。

const myArray = [ false, true ];
const myObject = { firstValue: false, secondValue: true };

const [ myProp, mySecondProp ] = myObject;
> Uncaught TypeError: myObject is not iterable

const { myElement, mySecondElement } = myArray;

myElement
> undefined

mySecondElement;
> undefined

数组的解构会按从左到右的顺序依序进行。每个 解构赋值中的标识符对应于 具有相同索引的数组:

const myArray = [ 1, 2, 3 ];
const [ myElement, mySecondElement, myThirdElement ] = myArray;

myElement;
> 1

mySecondElement;
> 2

myThirdElement;
> 3

这也是解构对象时的默认行为。但是,如果 解构赋值中使用的标识符与对象的键 系统会使用相应的属性来填充这些标识符 值,无论它们的指定顺序如何:

const myObject = { firstValue: 1, secondValue: 2, thirdValue 3 };
const { secondValue, thirdValue, firstValue } = myObject;

firstValue;
> 1

secondValue;
> 2

thirdValue;
> 3

您可以通过省略标识符来跳过这些元素:

const myArray = [ 1, 2, 3 ];
const [ firstValue,, secondValue ] = myArray;

firstValue;
> 1

secondValue;
> 3

通过解构语法,您还可以在应用解构时为其分配默认值 值可以是空槽(如稀疏数组),也可以是 undefined 值。

const myArray = [ true, ];
const [ firstValue = "Default string.", secondValue = "Default string." ] = myArray;

firstValue;
> true

secondValue;
> "Default string."

解构不会将值强制转换为特定的类型。这意味着 "falsy" 值,例如空 字符串 ("") 或 null 仍被视为有意义的解构值:

const myArray = [ false, null, 0, "",, undefined ];
const [ falseValue = true, nullValue = true, zeroValue = true, emptyStringValue = true, emptySlot = true, undefinedValue = true ] = myArray;

falseValue;
> false;

nullValue;
> null

zeroValue;
> 0

emptyStringValue;
> ""

emptySlot;
> true

undefinedValue;
> true

扩散运算符

使用 ES6 中引入的展开运算符 (...) 来扩展可迭代数据 数组、字符串或对象字面量转换为单个元素。 扩展运算符后面紧跟要扩展的数据结构 或包含该数据结构的变量的标识符。

const myArray = [ 1, 2, 3 ];

console.log( ...myArray );
> 1 2 3

分散语法主要用于复制和组合数组:

const myArray = [ 4, 5, 6 ];
const mySecondArray = [1, 2, 3, ...myArray ];

mySecondArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

您只能在以下上下文中使用展开语法:

对于数组和字符串,展开语法仅适用于零个或零个以上的参数 还是数组中的元素。第一个示例 本部分中的扩展运算符语法之所以有效,是因为它将 ...myArray 作为 内置 console.log 方法的参数。

例如,如果将展开的数据分配给外部变量, 另一个数组:

const myArray = [ 1, 2, 3 ];
const spreadVariable = ...myArray;
> Uncaught SyntaxError: Unexpected token '...'

但复制数组的方式是将原始数组扩展为数组字面量:

const myArray = [ 1, 2, 3 ];
const spreadArray = [ ...myArray ];

spreadArray;
> Array(3) [ 1, 2, 3 ]

如需将构成两个或多个数组的元素合并为一个数组,请执行以下操作:

const myArray = [ 1, 2, 3 ];
const mySecondArray = [ 4, 5, 6 ];
const myNewArray = [ ...myArray, ...mySecondArray ];

myNewArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

或者,将数组的元素作为单个参数在函数调用中传递:

const myArray = [ true, false ];
const myFunction = ( myArgument, mySecondArgument ) => {
    console.log( myArgument, mySecondArgument );
};

myFunction( ...myArray );
> true false

扩展运算符扩展, ES2018 中的对象字面量。 与数组一样,您可以使用扩展运算符来复制或合并对象:

const myObj = { myProperty : true };
const mySecondObj = { ...myObj };

mySecondObj;
> Object { myProperty: true }
const myFirstObj = { myProperty : true };
const mySecondObj = { additionalProperty : true };
const myMergedObj = { ...myFirstObj, ...mySecondObj };

myMergedObj;
> Object { myProperty: true, additionalProperty: true }

扩展运算符创建“浅层”副本。也就是说,它不会复制 原始对象的原型和不可枚举 属性。

const myCustomPrototype = { protoProp: "My prototype." };
const myObj = Object.create( myCustomPrototype, {
    myEnumerableProp: {
        value: true,
        enumerable: true
    },
    myNonEnumerableProp: {
        value: false,
        enumerable: false
    }
});
const myNewObj = { ...myObj };

myObj;
> Object { myEnumerableProp: true,  }
    myEnumerableProp: true
    myNonEnumerableProp: false
    <prototype>: Object { protoProp: "My prototype." }

myNewObj;
> Object { myEnumerableProp: true }
    myEnumerableProp: true
    <prototype>: Object {  }

请注意,数组和对象不能互换使用。禁止的行为 将对象扩展为数组,或将数组扩展为对象。

休息运算符

虽然运算符本身的语法相同,但其余运算符 (...) 根据其使用的上下文执行相反的函数。而不是 将可迭代数据结构扩展为单独的元素, 解构赋值,或将其定义为 函数参数不同,其余运算符可将 转换为可迭代数据结构。这个名称源于 用来收集“其余的”一组数据值。

与解构赋值搭配使用时,语法称为“rest 属性” 语法。

const myArray = [ "First", "Second", "Third", "Fourth", "Fifth" ];

[ myFirstElement, mySecondElement, ...remainingElements ] = myArray;

myFirstElement;
> "First"

mySecondElement;
> "Second"

remainingElements;
> Array(3) [ "Third", "Fourth", "Fifth"]

用于为函数提供无限多个参数时, 语法称为“rest 参数”语法:

function myFunction( ...myParameters ) {
    let result = 0;
    myParameters.forEach( ( myParam ) => {
        result += myParam;
    });
    return result;
};

myFunction( 2, 2 );
> 4

myFunction( 1, 1, 1, 10, 5 );
> 18

myFunction( 10, 11, 25 );
> 46

%TypedArray%

类型化数组是一项 ES6 功能,用于存储结构化二进制数据, 例如处理上传的文件或 WebGL

符号一样,%TypedArray% 固有函数(通常记录为 %TypedArray%@@TypedArray) 因此它不会被误认为是全局属性) 符合常规意义,您不能使用 new 调用它,也不能直接调用它。 相反,%TypedArray% 是指 构造函数,每个构造函数与特定的二进制数据格式兼容。通过 固有 %TypedArray% 父类提供具有以下特征的属性和实用程序方法: 所有 %TypedArray% 构造函数子类及其实例都会继承。

检查您的理解情况

假设 `const myArray = [ 30, 50, 70 ];` `myArray[1]` 是什么 退货?

50
30
70

如果 `myArray` 有三个值,`myArray[9]` 会返回什么?

Undefined
错误消息
9
Null