MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

JavaScript数组创建的创新方法

2022-04-031.5k 阅读

传统数组创建方式回顾

在深入探讨创新方法之前,先简要回顾一下JavaScript中传统的数组创建方式。

使用数组字面量

这是最常见的创建数组的方式,语法简洁明了。例如:

let fruits = ['apple', 'banana', 'cherry'];

这种方式直接用方括号 [] 来定义数组,并在其中列出数组元素。数组字面量创建的数组是一个JavaScript对象,它继承自 Array.prototype,这赋予了数组一系列的方法,比如 pushpopslice 等。

使用 new Array() 构造函数

可以通过 new Array() 构造函数来创建数组。有几种不同的调用方式:

  • 不传递参数,创建一个空数组:
let emptyArray = new Array();
  • 传递一个数字参数,创建一个指定长度的数组:
let arrayWithLength = new Array(5);
console.log(arrayWithLength.length); // 输出 5

这里需要注意,虽然数组长度为5,但实际上数组中并没有元素,它是稀疏数组。如果访问 arrayWithLength[0],会得到 undefined

  • 传递多个参数,创建一个包含这些参数的数组:
let numbers = new Array(1, 2, 3);

等同于 let numbers = [1, 2, 3];

利用 Array.from() 创建数组

Array.from() 是ES6引入的一个非常实用的方法,用于将类数组对象或可迭代对象转换为真正的数组。

类数组对象转换为数组

类数组对象是指具有 length 属性且属性名(键)为非负整数的对象。例如,函数内部的 arguments 对象就是一个类数组对象。

function convertArgsToArray() {
    return Array.from(arguments);
}
let result = convertArgsToArray(1, 2, 3);
console.log(result); // 输出 [1, 2, 3]

在上面的例子中,arguments 对象被 Array.from() 转换为了一个真正的数组。

可迭代对象转换为数组

可迭代对象是指实现了 Symbol.iterator 接口的对象。例如,SetMap 都是可迭代对象。

let set = new Set([1, 2, 2, 3]);
let setToArray = Array.from(set);
console.log(setToArray); // 输出 [1, 2, 3],Set 去重后的结果转换为数组

Array.from() 还接受第二个可选参数,即映射函数。这个映射函数会对每个元素进行处理后再放入新数组。

let numbers = Array.from({ length: 5 }, (_, i) => i + 1);
console.log(numbers); // 输出 [1, 2, 3, 4, 5]

这里,通过 { length: 5 } 创建了一个类数组对象,映射函数 (value, index) => index + 1 对每个元素进行处理,生成了从1到5的数组。

利用 Array.of() 创建数组

Array.of() 也是ES6引入的方法,它的目的是统一数组创建方式,避免 new Array() 构造函数在参数处理上的歧义。

消除 new Array() 的歧义

回顾前面提到的 new Array(),如果传递一个数字参数,它会创建一个指定长度的稀疏数组;而传递多个参数时,才会创建包含这些参数的数组。Array.of() 则不会有这种歧义。

let arr1 = Array.of(5);
console.log(arr1); // 输出 [5]
let arr2 = new Array(5);
console.log(arr2); // 输出长度为5的稀疏数组

Array.of() 总是创建一个包含所有传入参数的数组,无论参数的数量和类型。

let mixedArray = Array.of(1, 'two', true);
console.log(mixedArray); // 输出 [1, 'two', true]

基于函数生成数组

通过自定义函数来生成数组可以实现更复杂的逻辑。

递归函数生成数组

递归函数可以根据特定的逻辑逐步生成数组元素。例如,生成一个斐波那契数列的数组:

function fibonacciArray(n) {
    function fibonacci(i) {
        if (i <= 1) return i;
        return fibonacci(i - 1) + fibonacci(i - 2);
    }
    let result = [];
    for (let i = 0; i < n; i++) {
        result.push(fibonacci(i));
    }
    return result;
}
let fibArray = fibonacciArray(10);
console.log(fibArray); 
// 输出 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

在这个例子中,通过递归函数 fibonacci 计算斐波那契数列的每一项,并将其添加到数组 result 中。

迭代函数生成数组

迭代函数也可以用来生成数组。例如,生成一个指定范围内的偶数数组:

function generateEvenArray(start, end) {
    let result = [];
    for (let i = start; i <= end; i++) {
        if (i % 2 === 0) {
            result.push(i);
        }
    }
    return result;
}
let evenArray = generateEvenArray(2, 10);
console.log(evenArray); // 输出 [2, 4, 6, 8, 10]

这种方式通过迭代遍历指定范围,并根据条件筛选元素添加到数组中。

利用迭代器和生成器创建数组

迭代器和生成器是ES6引入的强大特性,它们可以用来创建数组。

迭代器创建数组

迭代器是一个对象,它定义了一个序列,并在终止时可能返回一个返回值。可以手动实现一个迭代器,然后利用 Array.from() 将其转换为数组。

let myIterator = {
    [Symbol.iterator]() {
        let i = 0;
        return {
            next() {
                if (i < 5) {
                    return { value: i++, done: false };
                }
                return { done: true };
            }
        };
    }
};
let iterToArray = Array.from(myIterator);
console.log(iterToArray); // 输出 [0, 1, 2, 3, 4]

这里,myIterator 实现了 Symbol.iterator 方法,返回一个具有 next 方法的对象。next 方法依次返回数组元素,Array.from() 将其转换为数组。

生成器创建数组

生成器是一种特殊的函数,它返回一个迭代器对象。生成器函数使用 function* 语法定义。

function* generateNumbers() {
    for (let i = 0; i < 3; i++) {
        yield i;
    }
}
let gen = generateNumbers();
let genToArray = Array.from(gen);
console.log(genToArray); // 输出 [0, 1, 2]

在生成器函数 generateNumbers 中,yield 关键字暂停函数执行并返回一个值。Array.from() 可以将生成器返回的迭代器转换为数组。

利用解构赋值创建数组

解构赋值不仅可以用于提取数组或对象的元素,还可以用于创建数组。

从已有数组解构创建新数组

可以从一个已有数组中提取部分元素并创建一个新数组。

let originalArray = [1, 2, 3, 4, 5];
let [a, b, ...rest] = originalArray;
console.log([a, b]); // 输出 [1, 2]
console.log(rest); // 输出 [3, 4, 5]

这里,通过解构赋值,将 originalArray 的前两个元素赋值给 ab,剩余元素赋值给 rest,从而创建了新的数组。

利用解构创建嵌套数组

解构赋值还可以用于创建嵌套数组。

let [nestedArray] = [[1, 2, 3]];
console.log(nestedArray); // 输出 [1, 2, 3]

在这个例子中,通过解构赋值从一个包含数组的数组中提取出内部数组。

利用对象属性创建数组

JavaScript对象的属性可以用来间接创建数组。

将对象属性值转换为数组

可以通过遍历对象的属性,将属性值收集到一个数组中。

let myObject = {
    prop1: 'value1',
    prop2: 'value2',
    prop3: 'value3'
};
let valuesArray = Object.values(myObject);
console.log(valuesArray); // 输出 ['value1', 'value2', 'value3']

Object.values() 方法返回一个包含对象自身可枚举属性值的数组。

利用对象属性名创建数组

类似地,可以利用对象的属性名来创建数组。

let myObject2 = {
    key1: 'value1',
    key2: 'value2',
    key3: 'value3'
};
let keysArray = Object.keys(myObject2);
console.log(keysArray); // 输出 ['key1', 'key2', 'key3']

Object.keys() 方法返回一个包含对象自身可枚举属性名的数组。

利用字符串创建数组

字符串在JavaScript中也可以作为创建数组的基础。

字符串分割为数组

split() 方法可以将字符串按照指定的分隔符分割成数组。

let sentence = 'Hello, world!';
let wordsArray = sentence.split(', ');
console.log(wordsArray); // 输出 ['Hello', 'world!']

如果不传递分隔符,split() 会将字符串的每个字符作为一个数组元素。

let charArray = 'abc'.split('');
console.log(charArray); // 输出 ['a', 'b', 'c']

从字符串重复创建数组

可以通过字符串的重复操作和分割来创建特定模式的数组。

let repeatedString = 'a,'.repeat(3).slice(0, -1);
let repeatedArray = repeatedString.split(',');
console.log(repeatedArray); // 输出 ['a', 'a', 'a']

这里,先通过 repeat() 方法重复字符串 'a,' 三次,然后使用 slice() 去掉最后一个多余的逗号,最后通过 split(',') 分割成数组。

利用函数式编程方法创建数组

函数式编程方法在JavaScript中也可以用于创建数组,特别是结合 mapreduce 等方法。

使用 map 创建数组

map 方法可以对数组中的每个元素进行处理,并返回一个新数组。可以从一个简单数组出发,利用 map 创建一个新的具有不同值的数组。

let numbers1 = [1, 2, 3];
let squaredNumbers = numbers1.map(num => num * num);
console.log(squaredNumbers); // 输出 [1, 4, 9]

也可以从一个非数组的可迭代对象出发,结合 Array.from()map 创建数组。

let set2 = new Set([1, 2, 3]);
let doubledSet = Array.from(set2).map(num => num * 2);
console.log(doubledSet); // 输出 [2, 4, 6]

使用 reduce 创建数组

reduce 方法可以通过对数组元素的累积计算来创建一个新数组。例如,将数组中的所有偶数提取出来组成一个新数组。

let numbers2 = [1, 2, 3, 4, 5];
let evenNumbers = numbers2.reduce((acc, num) => {
    if (num % 2 === 0) {
        acc.push(num);
    }
    return acc;
}, []);
console.log(evenNumbers); // 输出 [2, 4]

在这个例子中,reduce 方法从初始值 [] 开始,对 numbers2 中的每个元素进行检查,如果是偶数则添加到 acc 数组中,最后返回包含偶数的新数组。

利用数学方法创建数组

JavaScript的数学方法也可以辅助创建数组。

利用 Math.random() 创建随机数数组

Math.random() 方法返回一个介于0(包括)和1(不包括)之间的随机小数。可以利用它来创建包含随机数的数组。

function createRandomArray(length, min, max) {
    let result = [];
    for (let i = 0; i < length; i++) {
        let randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
        result.push(randomNumber);
    }
    return result;
}
let randomArray = createRandomArray(5, 1, 10);
console.log(randomArray); 
// 输出类似 [3, 7, 2, 9, 5] 的包含5个1到10之间随机整数的数组

这里通过 Math.random() 生成随机小数,再通过 Math.floor() 取整并调整范围,生成指定范围内的随机整数数组。

利用数学序列创建数组

可以根据数学序列的规律创建数组。例如,创建一个等差数列数组。

function createArithmeticArray(start, commonDiff, length) {
    let result = [];
    for (let i = 0; i < length; i++) {
        result.push(start + i * commonDiff);
    }
    return result;
}
let arithmeticArray = createArithmeticArray(1, 2, 5);
console.log(arithmeticArray); // 输出 [1, 3, 5, 7, 9]

这个函数根据等差数列的通项公式 a_n = a_1 + (n - 1)d(这里 a_1startdcommonDiffnlength)生成数组。

利用浏览器API创建数组

在浏览器环境中,一些API也可以用于创建数组。

利用 document.querySelectorAll() 创建数组

document.querySelectorAll() 方法返回一个 NodeList 对象,它是一个类数组对象,可以使用 Array.from() 将其转换为真正的数组。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Create Array from DOM</title>
</head>

<body>
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <script>
        let divs = document.querySelectorAll('.item');
        let divsArray = Array.from(divs);
        console.log(divsArray); 
        // 输出包含所有class为 'item' 的div元素的数组
    </script>
</body>

</html>

这样就可以方便地对DOM元素进行数组操作,比如遍历、筛选等。

利用 localStorage 创建数组

localStorage 可以存储字符串类型的数据。可以将数组转换为字符串存储,然后再转换回数组。

let myArray = [1, 2, 3];
localStorage.setItem('myArray', JSON.stringify(myArray));
let retrievedArray = JSON.parse(localStorage.getItem('myArray'));
console.log(retrievedArray); // 输出 [1, 2, 3]

这里先使用 JSON.stringify() 将数组转换为字符串存储在 localStorage 中,然后使用 JSON.parse()localStorage 中取出字符串并转换回数组。

总结与实践应用

通过上述多种创新的数组创建方法,我们可以根据不同的需求和场景选择最合适的方式。在实际项目中,比如数据处理、算法实现、前端页面渲染等方面,这些方法都能发挥重要作用。例如,在数据处理中,利用函数式编程方法和数学方法创建数组可以快速生成符合特定规律的数据;在前端页面渲染中,利用 document.querySelectorAll()Array.from() 可以方便地操作DOM元素数组。掌握这些创新方法能让开发者在JavaScript编程中更加得心应手,提高代码的效率和可读性。