这些问题看完,你就精通 JavaScript 的数组了

83 阅读5分钟

JavaScript数组有哪些常见的创建方法?

JavaScript数组可以使用数组字面量([])创建,也可以使用Array构造函数创建。例如:let arr = [1, 2, 3]let arr = new Array(1, 2, 3)

如何访问和修改数组中的元素?

通过索引来访问和修改数组中的元素。例如,arr[0] 就是访问数组arr中的第一个元素,arr[0] = 'new value' 就是修改第一个元素为 'new value'。

slicesplice 方法有什么区别?

slice() 方法返回一个新的数组对象,这一对象是一个由 beginend 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

  • begin:从该索引(包括)处开始提取原数组中的元素。如果该参数为负数,则它表示从原数组中的倒数第几个元素开始取,slice(-2) 表示提取原数组中的最后两个元素。
  • end:到该索引(不包括)处结束提取原数组中的元素。slice 方法提取的元素包括 begin,但不包括 end。换句话说,end 索引处的元素是不包括的。如果省略 end 参数,或者 end 大于数组的长度,slice 会提取到原数组末尾的所有元素。如果 end 为负数,表示从原数组最后一个元素开始的倒数第 end 个元素结束。
let numbers = [1, 2, 3, 4, 5];

console.log(numbers.slice(2));        // [3, 4, 5]
console.log(numbers.slice(2, 4));     // [3, 4]JavaScript 的数组中,索引是从 0 开始的。
所以 `numbers` 数组中索引 2 的元素是 3,索引 3 的元素是 4,索引 4 的元素是 5。

所以当你调用 `numbers.slice(2, 4)` 时,你得到的新数组就是 `[3, 4]`。
这是因为 `slice(2, 4)` 包含了开始的索引 2(元素 3),但不包括结束的索引 4(元素 5)。


console.log(numbers.slice(-2));       // [4, 5]
console.log(numbers.slice(1, -1));    // [2, 3, 4]

slice() 方法不会改变原数组,它返回的是一个新数组。

slice(begin, end) 会提取原数组从 begin 索引开始到 end 索引结束(但不包括 end 索引)的所有元素。


splice() 方法通过删除或替换现有元素或者添加新元素来改变一个数组的内容。它直接在原数组上进行操作。

let arr = ['zero', 'one', 'two', 'three'];
let spliced = arr.splice(1, 2, 'hello');

console.log(spliced); // ['one', 'two']
console.log(arr); // ['zero', 'hello', 'three']

什么是稀疏数组?

稀疏数组是包含从 0 开始的不连续索引的数组,即数组中有某些元素为空。

解释一下 pushunshift 的区别,以及它们对原数组的影响。

push 是在数组的末尾添加新元素,而 unshift 是在数组的开始添加新元素。它们都会修改原始数组,push 返回新的长度,unshift 同样返回新的长度。

popshift 有什么区别?**

pop 从数组的末尾删除一个元素并返回该元素,而 shift 从数组的开始删除一个元素并返回该元素。它们都会修改原始数组。

如何检查一个值是否存在于数组中?

可以使用 includes 方法,例如 arr.includes(value),或者使用 indexOf 方法,例如 arr.indexOf(value) !== -1

在处理大数组时,使用 forEach 循环和 for 循环有何区别?

在性能上,for 循环通常会比 forEach 快一些,因为 forEach 会为数组中的每个元素创建一个新的函数作用域。然而,forEach 循环的代码通常更简洁易读。在处理大数组时,要特别注意避免产生大量的函数作用域,这可能会对性能产生影响。

描述一下 mapfilterreduce 这几个函数的功能,并说明它们是否会改变原数组。

map 是用于遍历数组,并对每个元素进行某种操作,然后返回一个新的数组,它不会改变原始数组。filter 是根据某种条件过滤数组中的元素,同样返回一个新的数组,也不会改变原始数组。reduce 是对数组中的每个元素进行某种累积操作,最终返回一个单一的结果,它也不会改变原始数组。

都不会改变原数组

怎么看待直接修改数组索引的方式来添加元素?例如 arr[5] = 'new item'

直接修改数组的索引来添加元素可能会创建“空位”,这些位置被称为"稀疏数组"。在JavaScript中,稀疏数组可能会导致一些迭代方法(如mapforEach)的行为异常。

在处理数组时,你如何防止改变原数组?

我们可以使用 sliceconcat 方法或者扩展操作符 ... 来复制一个新的数组,然后操作新的数组,以此来防止改变原数组。

如何合并两个数组?

可以使用 concat 方法或者扩展操作符 ...。例如 arr1.concat(arr2) 或者 [...arr1, ...arr2]

如何将一个数组扁平化?

就是将一个嵌套多层的数组 array(嵌套可以是任何层数)转换为只有一层的数组。在处理数组数据时,有时可能会遇到多层嵌套的情况,如果我们需要对这些数据进行某些操作,如排序,查找等,这时,就需要将多层嵌套的数组“扁平化”。

例如,如果你正在处理一个用户的数据结构,该结构包括用户的个人信息和他们的订单信息。订单信息可能是一个嵌套数组,包含每个订单的详细信息。如果你需要对所有订单进行操作,那么你可能需要先将订单数组进行扁平化处理。

const arr = [1, [2, [3, [4, 5]]]];

const flatArr = arr.flat(Infinity);

console.log(flatArr); // [1, 2, 3, 4, 5]

怎么理解数组是对象的特殊形式这一说法?

在JavaScript中,数组其实是一种特殊的对象,索引其实就是属性名,只是这个属性名是数字。因此,数组除了有一些特殊的方法,比如 pushpop 等,还可以像普通对象一样添加属性和方法。

当数组的长度被手动改变时,会发生什么?

如果数组的长度被减小,那么超出新长度的部分会被删除;如果数组的长度被增大,那么新的元素会被初始化为 undefined