判断数组应使用Array.isArray()或Object.prototype.toString.call();push、pop、shift、unshift均修改原数组;map/filter/find/some/every语义不同且不改原数组;slice只读,splice修改原数组。

怎么判断一个变量是不是数组?别用 typeof
用 typeof [] 得到的是 "object",完全不可靠。真正安全的判断方式只有两个:Array.isArray() 或 Object.prototype.toString.call()。
-
Array.isArray([])→true,这是 ES5+ 标准推荐方法,兼容性好(IE9+) -
Object.prototype.toString.call([]) === '[object Array]'适合需要支持极老环境(如 IE6–8)的场景 - 避免用
instanceof Array:跨 iframe 时会失效,因为不同上下文的Array构造函数不相等
push、pop、shift、unshift 这四个方法改不改变原数组?
全部都会直接修改原数组,返回值也各不相同——这点容易混淆,尤其 shift 和 unshift 的返回值不是新长度而是被移除/插入的元素本身。
const arr = [1, 2, 3]; arr.push(4); // → 返回 4(新长度是 4),arr 变成 [1, 2, 3, 4] arr.pop(); // → 返回 4,arr 变成 [1, 2, 3] arr.shift(); // → 返回 1,arr 变成 [2, 3] arr.unshift(0); // → 返回 3(新长度),arr 变成 [0, 2, 3]
- 想“不改原数组”地加末尾元素?用扩展运算符:
[...arr, newItem] - 想删开头但保留原数组?用解构:
const [, ...rest] = arr -
push和unshift性能较差(尤其大数组),因为要移动所有后续元素;push比unshift快得多
map、filter、find、some、every 这些方法什么时候该用?
它们都不修改原数组,但语义和用途差异很大,选错会导致逻辑错误或性能浪费。
-
map:你要对每个元素做**转换**,且需要一个**等长新数组**(比如arr.map(x => x * 2)) -
filter:你要**筛选子集**,返回满足条件的元素组成的数组(比如arr.filter(x => x > 10)) -
find:你只要**第一个匹配项**,且不关心索引(返回值是元素本身,不是索引) -
some:你只关心“有没有至少一个满足”,返回布尔值,遇到第一个true就停止遍历 -
every:你只关心“是否全部满足”,也是布尔值,遇到第一个false就停止
注意:findIndex 和 indexOf 不同——前者接受函数,后者只支持严格相等;includes 是 indexOf !== -1 的语义糖,但不支持回调。
立即学习“Java免费学习笔记(深入)”;
splice 和 slice 容易搞混?关键看第三个参数
slice(start, end) 是纯读取,不改原数组;splice(start, deleteCount, ...items) 是写操作,会修改原数组并返回被删除的元素。
const arr = [1, 2, 3, 4, 5]; arr.slice(1, 3); // → [2, 3],arr 不变 arr.splice(1, 2); // → [2, 3],arr 变成 [1, 4, 5]
-
splice第二个参数为0时,只插入不删除(类似push/unshift的通用版) -
slice(0)是浅拷贝数组的常用写法,比arr.concat()或[...arr]更早被广泛使用 - 想删掉某个值的所有出现?不能只靠
splice一次调用,得配合循环或filter
实际项目里最常被忽略的是:所有这些方法对稀疏数组(比如 [1, , 3])的行为不一致,map 和 filter 会跳过空位,forEach 也会,但 for...in 会遍历索引属性,for...of 会把空位当作 undefined ——这种细节在处理用户上传的不规则数据时特别容易出 bug。











