数组是 JavaScript 中最常用的数据结构之一,但它的玩法可不止 "存数据" 这么简单!今天咱们就掰开揉碎,从初始化到遍历,再到那些容易踩坑的细节,一网打尽~ 👇
一、数组初始化:不止于 []
这么简单📦
数组的初始化方式五花八门,不同方式藏着不同的 "小心机",选错了可能踩坑哦!
1. 最直接:数组字面量 []
最简单的方式,直接把元素塞进方括号,像打包快递一样直观:
javascript
const arr = [1, 2, 3]; // 直接存放具体值,创建即能用✅
还能拼接数组:['蔡徐坤', '小黑子', ...arr]
👉 瞬间扩容,超方便!
2. 带 "坑" 的 new Array()
用 new Array(n)
创建指定长度的数组时,要注意它的 "empty" 特性:
javascript
const arr = new Array(5); // 创建后是 [empty × 5]
👉 这里的 "empty" 不是 undefined
,而是未分配键!所以 for...in
循环遍历不到(因为键没被创建),arr.hasOwnProperty(0)
会返回 false
。
想让它 "实" 起来?用 fill()
填充:
javascript
const arr2 = new Array(5).fill(undefined); // 变成 [undefined, undefined, ...]
这时 for...in
就能遍历了,arr2.hasOwnProperty(0)
也会返回 true
啦~
3. 静态方法:Array.of()
和 Array.from()
-
Array.of()
:专治 "不同值" 初始化,比new Array()
更靠谱:javascriptArray.of(1, 2, 3); // 直接得到 [1, 2, 3],不会像 new Array(3) 那样变成 empty
-
Array.from()
:神级转换工具,能把 "类数组" 转成数组,还能加计算:javascript// 生成 A-Z 字母数组(65 是 'A' 的 ASCII 码) Array.from(new Array(26), (val, index) => String.fromCharCode(index + 65));
简直是批量处理数据的神器!✨
二、数组遍历:选对方式少踩坑🔄
遍历数组的方法有很多,但不是所有方法都 "合群",选错了可能效率低或出 bug!
1. for...in
循环:谨慎使用!
for...in
本质是遍历 "对象的可枚举属性",数组用它会有坑:
-
会遍历原型链上的属性:比如给数组原型加个方法,
for...in
也会跑出来 -
对
new Array(5)
这种 empty 数组无效(因为没键可遍历)
例子:
javascript
const arr = [1, 2, 3];
// 给原型加个属性
arr.__proto__.extra = '坑';
for (let key in arr) {
console.log(key, arr[key]); // 会输出 0:1, 1:2, 2:3, extra:坑 ❌
}
👉 除非特意遍历原型链,否则别用它遍历数组!
2. for...of
循环:遍历数组的 "天选之子"
直接遍历元素,无视原型链,还支持 break
/continue
,超省心:
javascript
const arr = [1, 2, 3];
for (let item of arr) {
console.log(item); // 1, 2, 3 ✅
if (item === 2) break; // 能正常中断
}
想同时拿索引?用 entries()
方法:
javascript
for (const [index, value] of arr.entries()) {
console.log(`索引${index}:${value}`); // 索引0:1,索引1:2...
}
3. forEach()
:简洁但 "倔强"
forEach
是数组自带的遍历方法,写法简洁,但有个小脾气:
javascript
const names = ['Alice', 'Bob', 'Charlie'];
names.forEach(name => {
if (name === 'Charlie') {
return; // 这里的 return 只是跳过当前循环,不是终止整个遍历!
}
console.log(name); // 会输出 Alice, Bob(Charlie 被跳过,但循环继续)
});
👉 不能用 break
中断,想中途停?还是选 for...of
吧~
4. reduce()
:从 "多" 到 "一" 的魔法
reduce
能把数组 "浓缩" 成一个值,适合求和、统计等场景:
javascript
// 计算 1-6 的和
[1,2,3,4,5,6].reduce((prev, curr) => prev + curr, 0); // 结果 21
原理:每次用 "上一次的结果" 和 "当前元素" 计算,最后输出最终结果,超适合复杂逻辑!
三、数组与原型链:别被 "继承" 坑了🔍
JavaScript 数组本质是对象,会继承原型链上的属性,这可能让遍历出问题!
看个例子:
javascript
const obj = { name: '蔡徐坤' };
const obj2 = { skill: '小黑子' };
obj.__proto__ = obj2; // obj 继承 obj2 的属性
for (let key in obj) {
console.log(obj[key]); // 会输出 '蔡徐坤' 和 '小黑子'(继承来的也被遍历了)
}
// 用 hasOwnProperty 区分"自身属性"和"继承属性"
obj.hasOwnProperty('name'); // true(自身的)
obj.hasOwnProperty('skill'); // false(继承的)
数组也一样!for...in
会遍历数组原型链上的属性,所以判断一个键是不是数组自身的,要用 arr.hasOwnProperty(index)
。
另外,new Array(5)
创建的数组,arr.hasOwnProperty(0)
是 false
(因为键未分配),而 fill
之后会变成 true
,这点要记牢哦~
总结:数组使用小口诀📝
-
初始化:简单用
[]
,指定长度加fill
,不同值用of
,转换用from
; -
遍历:
for...of
最靠谱,forEach
别想break
,for...in
慎用于数组; -
原型坑:
hasOwnProperty
来区分,自身属性才靠谱。
掌握这些细节,你的数组操作会更丝滑~ 下次写代码,再也不怕数组 "调皮" 啦!😉