JavaScript数组的三种创建方式详解

发表时间: 2024-06-05 14:07

JavaScript备忘录 —— 创建数组的3种方式

1 # 直接声明

JavaScript是弱类型语言,因此你可以直接将一个数组赋值给一个变量,即创建了一个数组:

let arr = [1, 2, 3];


绝大多数情况下使用的都会使用这种语法创建/声明数组。其中数组使用中括号 [...] 包裹,元素之间用逗号 , 分隔。

有时为了代码优雅,遇到数组元素很长很多时,也可以采用换行方式编写:

let fruit - [    "apple",    "banana",    "orange",    "..."]


2 # 以对象方式创建数组

这是创建数组的另一种语法,即使用构造函数 Arrary():

let arr = new Array();let arr = Array();


备注: 调用 Array() 时可以使用或不使用 new。两者都会创建一个新的 Array 实例。但出于编程规范,建议使用 new 关键字。

用这种方式创建数组是,里面的参数有两种使用情况:

1. 仅一个Number类型参数

let arr = new Array(6);


当只传入一个 Number类型 的参数时,传入的参数则会被认定为是所创建数组的长度,而非元素。且这个数组仅有长度没有任何元素,若访问则是undefined。

补充知识:

含空槽的数组又被称作为稀疏数组。稀疏数组在使用数组迭代方法时,空槽元素都将被跳过。如果访问空槽元素,结果会是 undefine。

let arr = new Array(6);console.log(arr); // [ <6 empty items> ]console.log(arr[0]); // undefinedconsole.log(arr.length); // 6


2. 有一个非Number类型参数 或 有多个参数

续上回,如只有一个参数但不是 Number类型,则参数会被正常认定为是数组的一个元素

let arr = new Array("hello");console.log(arr); // [ 'hello' ]console.log(arr[0]); // helloconsole.log(arr.length); // 1


有多个参数,则效果就如同使用[...]声明数组一样,所有参数都被视作数组的元素。

let arr = new Array("hello", "world", "!");console.log(arr); // [ 'hello', 'world', '!' ]console.log(arr.length); // 3


此种方式一般不会使用,不但有可能会引起一些误会,也没有中括号[...]方式简洁。

3 # 使用 Array.from() 方法创建

上面两种创建数组的基础方式都无法创建一个初始化的数组,这在一些情况下无法满足我们的需求,例如创建哈希数组等等。这便是 Array.from() 能解决的第一个问题。

Array.from() 是一个全局下的静态方法,其作用是从可迭代或类数组对象创建一个新的浅拷贝的数组实例。不仅如此,还可以附带一个映射函数为数组内部的元素进行初始化操作。

首先我们先搞明白Array.from()要求传入的第一个参数 —— 一个 类数组对象可迭代对象

1. 由类数组对象创建数组

该方法会根据类数组对象创建一个长度为length的数组,其中的元素key是合理下标值的元素。

什么是类数组对象?

顾名思义,就是形似数组的对象。对象的属性都含有key与value,而这个关系也可以看作是数组的下标的关系——key为下标,value为值。此外还有一个特别的key是length,用于表示数组长度。

类数组对象还有个别名叫arguments对象。

所以一个形似数组的对象是:

javascript

复制代码

let arguments = { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }

同时,这里举几个用不符合规则的类数组对象创建数组的样例:

  • 长度与元素数量不符

元素数量会严格按照length的值执行。如果没有length,则默认为0——即一个空数组。

let arguments = {    0: 1,    1: 2,    2: 3,    length: 4}let arr = Array.from(arguments);console.log(arr); // [1, 2, 3, undefined]


let arguments = {    0: 1,    1: 2,    2: 3,    length: 0}let arr = Array.from(arguments);console.log(arr); // []


  • 键值不符合下标规范

如键值不符合下标规范,则这个键值对会被直接忽略。其它符合规则的键值对则被当作数组元素。

let arguments = {    0: 1,    1: 2,    3: 3,    length: 4}let arr = Array.from(arguments);console.log(arr); // [1, 2, undefined]


2. 由可迭代对象创建数组

除了从类数组对象创建数组,Array.from()也可以从任何可迭代对象创建数组。

什么是可迭代对象?

可迭代对象是实现了[Symbol.iterator]方法的对象,这个方法返回一个迭代器。这个迭代器对象又具有next()方法,每次调用next()方法就会返回一个包含value和done属性的对象,用于遍历该可迭代对象。

常见的内置可迭代对象有:

String Array TypedArray(例如 Uint8Array) NodeList HTMLCollection arguments对象 用户自定义的可迭代对象

比如从String创建数组:

let str = 'hello';let arr = Array.from(str);console.log(arr); // ["h", "e", "l", "l", "o"]


再比如从Set创建数组:

let set = new Set([1, 2, 3]);let arr = Array.from(set);console.log(arr); // [1, 2, 3]


3. 映射函数

除此之外,Array.from()还可以接受第二个参数,作为一个映射函数,用于对每个元素进行处理后再放入新数组,达到初始化的效果:

let set = new Set([1, 2, 3]);let arr = Array.from(set, x => x * x);console.log(arr); // [1, 4, 9]


这个映射函数类似于数组的 map() 方法:

关于 map() 方法

map()的作用是创建一个新数组,其中每个元素都由原数组中的每个元素都调用一次提供的函数后的返回值组成。

map()包含两个参数:

callbackFn:为数组中的每个元素执行的函数。它的返回值作为一个元素被添加为新数组中。

thisArg(可选):执行 callbackFn 时用作 this 的值。

其中的callbackFn被调用时将传入 3 个参数:

currentValue: 正在处理的当前元素。 index(可选): 正在处理的当前元素的索引。 array(可选): 调用了 map() 的数组本身。

但是Array.from()中的映射函数被调用时只传入 2 个参数(element、index),不接受 map() 中callbackFn的第三个参数array。因为Array.from()的执行过程中数组仍然在构建

除此之外,Array.from() 方法还接受第三个可选参数,这个参数被称为"this 值",与map()的thisArg参数一致。

let person = {  name: 'John',  sayHello: function() {    return `Hello, my name is ${this.name}`;  }};let nameArr = Array.from([1, 2, 3], function() {  return this.sayHello();}, person);console.log(nameArr); // ["Hello, my name is John", "Hello, my name is John", "Hello, my name is John"]


所以可以说Array.from(obj, mapFn, thisArg) 和 Array.from(obj).map(mapFn, thisArg) 会具有相同的结果。只是Array.from()不会创建中间数组,而是直接构建一个新数组。

Array.from() 映射函数使用案例

  • 初始化哈希函数
let hash = Array.from({length: 26}, (item) => item = 0);


  • 将字符串转换为大写
let str = 'hello';let arr = Array.from(str, (char) => char.toUpperCase());console.log(arr); // ["H", "E", "L", "L", "O"]


  • 平方数组元素
let numbers = [1, 2, 3, 4, 5];let squaredNumbers = Array.from(numbers, (x) => x * x);console.log(squaredNumbers); // [1, 4, 9, 16, 25]


  • 获取元素及其索引
let colors = ['red', 'green', 'blue'];let colorDetails = Array.from(colors, (color, index) => `${index}. ${color}`);console.log(colorDetails); // ["0. red", "1. green", "2. blue"]


  • 使用箭头函数作为映射函数
let set = new Set([1, 2, 3]);let doubledSet = Array.from(set, x => x * 2);console.log(doubledSet); // [2, 4, 6]


总结

在JavaScript中,创建数组3 种主要方式,每种方式都有其独特的特点和适用场景,选择合适的数组创建方式可以提高代码的可读性和性能。

直接声明

  • 特点:语法简洁、直观,适用于大部分场景。
  • 使用场景:适合绝大多数的数组创建需求,尤其是需要创建包含已知元素的数组。
  • 案例

let arr = [1, 2, 3];

let fruits = [

"apple",

"banana",

"orange",

"..."

];

以对象方式创建数组

  • 特点:使用Array()构造函数,可以创建空数组或指定长度的数组。适用于一些特殊情况。
  • 使用场景:适合需要创建特定长度的空数组或从单个非数字参数创建数组的情况。
  • 案例

let arr = new Array(6); // 创建一个长度为6的空数组

let singleElementArray = new Array("hello"); // 创建一个包含单个元素的数组

let multipleElementsArray = new Array("hello", "world", "!"); // 创建一个包含多个元素的数组

使用Array.from()方法创建:

  • 特点:从类数组对象或可迭代对象创建数组,同时可以使用映射函数对数组元素进行初始化操作。
  • 使用场景:适合从类数组对象(如arguments对象)、可迭代对象(如Set、String)创建数组,或需要对元素进行初始化操作时使用。
  • 案例

// 从类数组对象创建数组

let arguments = {

0: 1,

1: 2,

2: 3,

length: 4

};

let arr = Array.from(arguments);

console.log(arr); // [1, 2, 3, undefined]

// 从字符串创建数组

let str = 'hello';

let strArray = Array.from(str);

console.log(strArray); // ["h", "e", "l", "l", "o"]

// 使用映射函数

let numbers = [1, 2, 3, 4, 5];

let squaredNumbers = Array.from(numbers, x => x * x);

console.log(squaredNumbers); // [1, 4, 9, 16, 25]


作者:Dikkoo
链接:
https://juejin.cn/post/7376575006535237669