JS 数组

目标

知道什么是数组

会创建数组

知道如何访问和遍历数组

知道如何对数组元素进行新增、修改、删除、排序

能够独立完成经典的数组排序程序------冒泡排序和插入排序

一、数组的概念

问:什么是数组呢?

答:数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的方式。

二、创建数组

++创建数组++ 的两种常见方式的用法:

p使用" "字面量来创建数组,最常用的方式

p使用"new Array()"创建数组(后续学完对象就会明白为什么这样创建了)

//使用字面量\[\]创建数组(实际开发中,最常用)
var arr1= \[\]; // 创建一个空数组
// 数组里面可以存放任意类型的数据
var arr2 = 1,true,null,'abc',undifined; // 创建一个带初始值的数组

//使用 new Array() 创建数组
var arr3 = new Array(); // 创建了一个空数组
var arr4 = new Array('hello world');
var arr5 = new Array(5); // 创建一个数组长度为5的空数组

注意:new A rray() 字母A必须大写

new A rray(length)创建指定长度length的数组

数组是一种复杂的数据类型,属于Object(对象)类型,用

typeof检测 返回值是object

题外话:那如何能用创建对象的方法创建出 1 这种数组?

方法一:ES6 专门为了解决这个问题,出了 Array.of(),无论传几个数字,都当作元素:

方法二:new Array () + fill ():

"++数组名.length++ "来快速地获取数组长度。

for-in循环

语法

复制代码
for (const 变量 in 对象) {
  // 循环体
}

注意:变量得到的是下标(索引),不是元素本身

举例:

for-in循环的一个坑:for...in 会遍历自定义属性,不适合遍历数组!

遍历对象示例

复制代码
const person = {
  name: "张三",
  age: 18,
  gender: "男"
};

// key 是每一个属性名(字符串类型)
for (const key in person) {
  console.log(key, person[key]);
}
// 输出:
// name 张三
// age 18
// gender 男

数组是特殊的对象,因此可以加上自定义属性

方式三:for-of循环

一、核心作用

专门遍历可迭代对象 (Array、String、Map、Set、arguments、NodeList 等),直接拿到元素值 ,不会遍历原型属性,顺序稳定。 不能遍历普通 {} 对象(普通对象不可迭代)。

二、基础语法

复制代码
for (const 变量 of 可迭代对象) {
  // 循环体
}

三、常用示例

1. 遍历数组

复制代码
const arr = [10, 20, 30];
for (const item of arr) {
  console.log(item); // 10 20 30
}
需要索引怎么办:Array.prototype.entries()
复制代码
const arr = ['a','b','c'];
for (const [idx, val] of arr.entries()) {
  console.log(idx, val);
}
// 0 'a'
// 1 'b'
// 2 'c'

2. 遍历字符串

复制代码
const str = 'hello';
for (const char of str) {
  console.log(char); // h e l l o
}

3. 遍历 Set

复制代码
const s = new Set([1,2,2,3]);
for (const v of s) {
  console.log(v); // 1 2 3
}

4. 遍历 Map

复制代码
const m = new Map([['name','张三'],['age',18]]);
for (const [key, val] of m) {
  console.log(key, val);
}

5. 遍历 DOM 节点集合

复制代码
const lis = document.querySelectorAll('li');
for (const li of lis) {
  li.style.color = 'red';
}
  1. ECMAScript6 新增的一种循环方式,也是for循环的变体;
  2. for-of这是最简洁、最直接的遍历数组元素的方法,避开for-in的缺陷,

可以正确响应break、continue和return语句。

使用 break /continue

for...of 支持中断循环,这点优于 forEach(forEach 不能直接 break):

复制代码
const arr = [1,2,3,4];
for (const v of arr) {
  if(v === 3) break;
  console.log(v); // 1 2
}

表格

循环 用途 返回内容
for...in 遍历对象键名 属性名(字符串)
for...of 遍历可迭代对象 (数组 / Set/Map) 元素值
普通 for 数组精准遍历 数字下标

Array.prototype.forEach()

一、基础说明

forEach 是数组实例方法,遍历数组每一项,执行回调函数 ,无返回值,无法使用 break /continue 中断循环

语法

复制代码
arr.forEach(function(item, index, arr) {
  // 循环逻辑
}, thisArg)

参数:

  1. item:当前遍历元素
  2. index:当前元素下标(可选)
  3. arr:原数组本身(可选)
  4. thisArg:回调内 this 指向(可选)

二、基础示例

复制代码
const arr = [10, 20, 30];

// 普通函数写法
arr.forEach(function(item, idx) {
  console.log(idx, item);
});

// 箭头函数(最常用)
arr.forEach(item => {
  console.log(item);
});

三、thisArg 修改回调 this 指向

复制代码
const obj = { name: "测试" };
const arr = [1, 2];

arr.forEach(function(item) {
  console.log(this.name, item); // this 指向 obj
}, obj);

注意:箭头函数不绑定 this,写 thisArg 无效。

四、关键特性(重点坑点)

1. 不能 break、continue 终止循环

复制代码
const arr = [1,2,3];
arr.forEach(item => {
  if (item === 2) {
    break; // Uncaught SyntaxError
  }
})

想要中途跳出:改用 for / for...of,或使用 some() / every()

2. 没有返回值

复制代码
const res = [1,2].forEach(item => item * 2);
console.log(res); // undefined

需要生成新数组请用 map

3. 空值空位会跳过

复制代码
const arr = [1,,3];
arr.forEach(item => console.log(item));
// 输出:1  3,中间空位直接忽略

4. 遍历过程修改原数组长度会错乱

遍历索引是一开始就全部确定的,动态增删元素会漏遍历:

复制代码
const arr = [1,2,3];
arr.forEach((v,i)=>{
  arr.push(v);
  console.log(v);
})
// 只会打印1、2、3,新增元素不会遍历

五、如何实现 "中断 forEach" 替代方案

方案 1:Array.some () 返回 true 终止遍历

复制代码
const arr = [1,2,3,4];
arr.some(item => {
  if (item === 3) return true; // 返回true直接停止
  console.log(item);
});
// 输出 1 2

方案 2:Array.every () 返回 false 终止遍历

复制代码
arr.every(item => {
  if (item === 3) return false;
  console.log(item);
  return true;
});

六、forEach vs for...of/for...in 对比

表格

方式 能否中断 break 返回值 适用场景
forEach ❌ 不能 undefined 单纯遍历执行操作,不需要跳出
for...of ✅ 支持 break 需要中途终止、遍历数组 / Set/Map
for...in ✅ 支持 break 遍历对象属性,不推荐数组

数组合并成一个字符串

JS 数组合并为字符串 四种常用方法

1. Array.join () 【最推荐】

语法:数组.join(分隔符)

  • 不传参数:默认用逗号 , 拼接

  • 传空字符串 '':直接无缝拼接

  • 传自定义符号:' ''-''|'

    const arr = ['苹果','香蕉','橙子'];

    // 逗号分隔
    console.log(arr.join()); // 苹果,香蕉,橙子

    // 空格分隔
    console.log(arr.join(' ')); // 苹果 香蕉 橙子

    // 无缝拼接
    console.log(arr.join('')); // 苹果香蕉橙子

    // 横线分隔
    console.log(arr.join('-')); // 苹果-香蕉-橙子

特点:最简单、性能最好 ,会自动忽略数组空位 [,]

2. toString()

自动用逗号拼接,不能自定义分隔符

复制代码
const arr = [10,20,30];
console.log(arr.toString()); // "10,20,30"

3. 模板字符串 / 扩展运算符 ...

复制代码
const arr = ['a','b','c'];
const str = `${arr}`; // 等价 arr.toString() "a,b,c"

// 想要无缝拼接搭配 join
const str2 = [...arr].join('');
console.log(str2); // abc

4. reduce 累加拼接(适合复杂处理)

reduce 完整语法

复制代码
arr.reduce((累加器, 当前项, 索引, 原数组) => {
  处理逻辑
}, 初始值)

四个参数逐个解释:

  1. 累加器 res(第一个参数) 保存上一次循环拼接好的字符串,每一轮循环都会更新。
  2. 当前项 item(第二个参数) 数组现在遍历到的那一个元素。
  3. 索引 index(第三个,可选) 当前元素下标,0、1、2......
  4. 原数组 arr(第四个,可选) 正在遍历的完整数组,几乎很少用。

最后逗号后面的 ''初始值 第一次循环时,res 的初始内容。拼接字符串必须给空字符串 '',不然会出问题。

适合遍历时同时做数据处理再合并

  • res:半成品字符串,存之前拼好的内容
  • item:现在要加进来的新片段
  • '':循环开始前,半成品是空字符串

简单记忆: reduce(半成品, 当前内容 => 新半成品, 初始半成品)

复制代码
const arr = [1,2,3,4];
// 全部拼接
const str = arr.reduce((res, item) => res + item, '');
console.log(str); // "1234"

// 中间加分隔符
const str2 = arr.reduce((res, item, index) => {
  if(index === 0) return item;
  return res + '-' + item;
}, '');
console.log(str2); // "1-2-3-4"

方法对比

表格

方法 自定义分隔符 适用场景
join() ✅ 支持 日常绝大多数场景(首选)
toString() ❌ 只能逗号 简单快速输出
reduce ✅ 可自定义逻辑 需要遍历加工元素再拼接

字符串分割成数组:split()

基础语法

复制代码
str.split(分割符, 限制个数)
  • 返回:新数组
  • 分割符:决定在哪切开字符串

1. 按逗号分割(最常用)

复制代码
let str = "苹果,香蕉,橘子";
let arr = str.split(",");
console.log(arr); // ["苹果", "香蕉", "橘子"]

2. 按空格分割

复制代码
let str = "a b c d";
let arr = str.split(" ");
console.log(arr); // ["a", "b", "c", "d"]

3. 每个字符单独切开(分割符传空字符串 ''

复制代码
let str = "hello";
let arr = str.split("");
console.log(arr); // ["h","e","l","l","o"]

4. 按横线、特殊符号分割

复制代码
let str = "2026-06-16";
let arr = str.split("-");
console.log(arr); // ["2026","06","16"]

5. 第二个参数:限制返回数组长度

只取前 2 个元素:

复制代码
let str = "1,2,3,4";
let arr = str.split(",", 2);
console.log(arr); // ["1","2"]

6. 不传分割符:整个字符串变成单元素数组

复制代码
let str = "abc";
let arr = str.split();
console.log(arr); // ["abc"]

7. 复杂分割:多个分隔符(正则)

比如同时按逗号 / 空格分割:

复制代码
let str = "张三,李四 王五";
let arr = str.split(/[, ]/);
console.log(arr); // ["张三","李四","王五"]

配套记忆(和 join 对应)

  • 数组 → 字符串:arr.join('分隔符')
  • 字符串 → 数组:str.split('分隔符') 两者互为反向操作。

常见小坑

  1. 字符串首尾有分隔符,会出现空元素

    let str = ",a,b,";
    console.log(str.split(",")); // ["", "a", "b", ""]

  2. 连续分隔符也会产生空位

    "1,,2".split(","); // ["1", "", "2"]

数组添加元素 4 种常用方法

1. push () 末尾添加(最常用)

作用:在数组最后面追加元素,可加多个,返回新数组长度

复制代码
const arr = [1, 2];
let len = arr.push(3); 
console.log(arr); // [1,2,3]
console.log(len); // 3

// 一次性加多个
arr.push(4, 5, 'a');
console.log(arr); // [1,2,3,4,5,"a"]

2. unshift () 头部添加

作用:在数组开头插入元素,返回新长度,会改变原有元素下标

复制代码
const arr = [3,4];
arr.unshift(1, 2);
console.log(arr); // [1,2,3,4]

3. splice () 指定位置插入(万能增删改)

语法:arr.splice(起始索引, 删除个数, 要插入的元素) 删除个数写 0 = 只插入不删除

复制代码
const arr = [1,4,5];
// 在下标1的位置插入 2、3
arr.splice(1, 0, 2, 3);
console.log(arr); // [1,2,3,4,5]

4. 扩展运算符 ... 生成新数组(不修改原数组)

不会改变原数组,返回全新数组,适合函数式开发

复制代码
const arr = [2,3];
// 头部加
const newArr1 = [1, ...arr];
console.log(newArr1); // [1,2,3]

// 尾部加
const newArr2 = [...arr, 4];
console.log(newArr2); // [2,3,4]

// 中间插入
const newArr3 = [arr[0], 99, ...arr.slice(1)];
console.log(newArr3); // [2,99,3]

补充:concat () 拼接数组,生成新数组

用来把数组 / 元素合并,原数组不变

复制代码
const arr = [1,2];
const newArr = arr.concat(3, [4,5]);
console.log(newArr); // [1,2,3,4,5]
console.log(arr); // [1,2] 原数组不变

方法对比

表格

方法 添加位置 是否修改原数组 返回值
push 末尾 ✅ 修改 新长度
unshift 开头 ✅ 修改 新长度
splice 任意索引 ✅ 修改 被删除元素数组
... 扩展符 自定义 ❌ 不修改 新数组
concat 末尾拼接 ❌ 不修改 新数组

数组删除元素 全套方法

一、修改原数组(直接改变数组本身)

1. pop () 删除最后一个元素

  • 删除尾部元素,返回被删掉的值

    const arr = [10,20,30];
    let del = arr.pop();
    console.log(arr); // [10,20]
    console.log(del); // 30

2. shift () 删除第一个元素

  • 删除头部元素,返回被删掉的值

    const arr = [10,20,30];
    let del = arr.shift();
    console.log(arr); // [20,30]
    console.log(del); // 10

3. splice (起始下标,删除数量) 万能删除

语法:arr.splice(index, count) 返回:被删除元素组成的数组根据值删除元素示例

复制代码
let arr = [1,2,3,4];
let target = 3;
let idx = arr.indexOf(target);
if(idx !== -1){
  arr.splice(idx, 1);
}
console.log(arr); // [1,2,4]

4. 直接清空数组

复制代码
let arr = [1,2,3];
arr.length = 0;
console.log(arr); // []

二、不修改原数组(返回新数组,推荐函数式)

1. filter () 过滤删除(最常用)

保留满足条件的元素,过滤掉要删除的,原数组不变

复制代码
const arr = [1,2,3,4];
// 删除等于3的元素
const newArr = arr.filter(item => item !== 3);
console.log(newArr); // [1,2,4]
console.log(arr); // [1,2,3,4] 原数组不变

// 删除多个值
const list = [10,20,30,40];
const delArr = [20,40];
const res = list.filter(v => !delArr.includes(v));
console.log(res); // [10,30]

2. slice () 截取,间接实现删除

slice(起始,结束) 截取一段,不修改原数组

复制代码
const arr = [1,2,3,4];
// 删除下标2的元素:拼接前半段 + 后半段
const newArr = [...arr.slice(0,2), ...arr.slice(3)];
console.log(newArr); // [1,2,4]

三、删除指定下标元素对比总结

表格

方法 是否改原数组 作用 返回值
pop() ✅ 改变 删除最后一位 被删除元素
shift() ✅ 改变 删除第一位 被删除元素
splice(i, n) ✅ 改变 指定位置删除 n 个 删除的元素数组
filter() ❌ 不改变 按条件过滤删除 过滤后的新数组
slice + 扩展符 ❌ 不改变 截取拼接删除 新数组

四、常见坑

  1. delete arr[index] 不推荐 只会清空对应位置为 empty,数组长度不变,产生空位

    let arr = [1,2,3];
    delete arr[1];
    console.log(arr); // [1, empty, 3]
    console.log(arr.length); // 3

  2. splice 传负数下标会从尾部倒数截取,容易删错

  3. filter 适合批量删除、多条件过滤;splice 适合原地单元素删除

数组元素查找

一、查找下标(返回索引 /-1)

1. indexOf (值)

从前向后找,返回第一个匹配元素下标 ,找不到返回 -1 只能查基础类型(数字、字符串),不能查对象 / 数组

复制代码
const arr = [10, 20, 30, 20];
console.log(arr.indexOf(20)); // 1
console.log(arr.indexOf(99)); // -1

// 第二个参数:从指定下标开始查找
console.log(arr.indexOf(20, 2)); // 3

2. lastIndexOf (值)

从后往前找,返回最后一个匹配下标

复制代码
console.log(arr.lastIndexOf(20)); // 3

3. findIndex (回调)

根据条件查找下标 ,支持对象、复杂判断,找到第一个匹配下标,无返回 -1

复制代码
const list = [
  { id: 1, name: '张三' },
  { id: 2, name: '李四' }
];
// 找id=2的下标
const idx = list.findIndex(item => item.id === 2);
console.log(idx); // 1

二、查找元素本身(返回元素 /undefined)

1. find (回调)

返回第一个满足条件的元素 ,找不到返回 undefined 最常用查找对象数组

复制代码
const target = list.find(item => item.id === 1);
console.log(target); // {id:1,name:'张三'}

const none = list.find(item => item.id === 99);
console.log(none); // undefined

三、判断是否存在(返回布尔 true/false)

1. includes (值)

直接判断数组是否包含该值,返回布尔,简单好用

复制代码
const arr = [1,2,3];
console.log(arr.includes(2)); // true
console.log(arr.includes(9)); // false

缺点:同样不支持对象匹配

2. some (回调)

只要有一个满足条件就返回 true,适合对象数组判断存在

复制代码
const has = list.some(item => item.name === '李四');
console.log(has); // true

3. every (回调)

判断所有元素都满足条件,多用于校验全部数据

复制代码
const allIdGt0 = list.every(item => item.id > 0);
console.log(allIdGt0); // true

四、批量查找(过滤出所有符合条件元素)

filter (回调)

返回所有匹配元素组成的新数组 ,找不到返回空数组 []

复制代码
const nums = [1, 5, 8, 10, 15];
// 找出大于5的所有数字
const res = nums.filter(v => v > 5);
console.log(res); // [8,10,15]

五、方法对比速记

表格

方法 返回值 适用场景 能否查对象
indexOf 下标 /-1 简单值精确匹配
includes true/false 判断是否包含简单值
find 匹配元素 /undefined 获取第一个符合条件对象
findIndex 下标 /-1 获取第一个符合条件对象下标
some true/false 判断是否存在符合条件对象
filter 全部匹配元素数组 取出所有符合条件数据

六、常用场景示例

  1. 简单数字 / 字符串判断有无

    const arr = ['a','b','c'];
    if(arr.includes('b')){
    console.log('存在');
    }

  2. 对象数组找一条数据

    const user = list.find(v => v.id === 2);
    if(user){
    console.log('找到用户', user);
    }

  3. 判断对象是否存在

    if(list.some(v => v.name === '张三')){
    console.log('有张三');
    }

  4. 取出所有符合条件数据

    const bigNums = [1,2,10,20].filter(v => v > 5);

小坑提醒

  1. indexOf / includes 匹配引用类型(对象、数组)永远返回 - 1/false,因为地址不同

    const arr = [{a:1}];
    console.log(arr.includes({a:1})); // false

  2. 查找对象一律用 find / findIndex / some / filter

数组映射(Array Map

数组映射核心方法:map(),作用是遍历数组,对每个元素执行处理,返回长度相同的新数组,不修改原数组

一、JavaScript Array.map ()

语法

复制代码
const newArr = 原数组.map((item, index, arr) => {
  // 处理逻辑,必须return返回新元素
  return 处理后的值
})

参数说明:

  1. item:当前遍历元素(必选)
  2. index:当前元素下标(可选)
  3. arr:原数组本身(可选)

示例 1:基础数值转换

复制代码
const nums = [1,2,3,4]
// 每个数字乘2
const double = nums.map(n => n * 2)
console.log(double) // [2,4,6,8]
console.log(nums) // [1,2,3,4] 原数组不变

示例 2:对象数组映射(最常用)

接口返回原始数据,映射成页面需要的格式:

复制代码
const list = [
  { id:1, name:"小明", age:18 },
  { id:2, name:"小红", age:20 }
]
// 只提取需要字段,新增标签
const tableData = list.map(item => ({
  label: item.name,
  value: item.id,
  desc: `${item.name}今年${item.age}岁`
}))
console.log(tableData)
/*
[
  { label: '小明', value: 1, desc: '小明今年18岁' },
  { label: '小红', value: 2, desc: '小红今年20岁' }
]
*/

示例 3:带索引

复制代码
const words = ["a","b","c"]
const withIndex = words.map((w, i) => `${i+1}.${w}`)
// ["1.a","2.b","3.c"]

二、map 与 forEach 区别

表格

方法 返回值 是否改变原数组 使用场景
map 返回新数组 不修改原数组 需要转换、生成新数组
forEach 返回 undefined 不修改原数组 仅遍历执行操作,不需要新数组

错误示范:map 不写 return,新数组全是undefined

复制代码
const arr = [1,2,3]
const res = arr.map(n => { n+1 }) // 无return
console.log(res) // [undefined, undefined, undefined]

数组排序

一、核心方法:Array.sort()

特性

  1. 原地排序:直接修改原数组
  2. 无参数时:把元素转字符串,按 Unicode 编码排序(数字会出错)
  3. 接收回调函数 (a, b) => 数值 自定义规则
    • 返回 负数:a 放前面(升序)
    • 返回 正数:b 放前面(降序)
    • 返回 0:顺序不变

1. 数字数组排序

升序(从小到大)

复制代码
const arr = [12, 3, 45, 7, 2];
arr.sort((a, b) => a - b);
console.log(arr); // [2, 3, 7, 12, 45]

降序(从大到小)

复制代码
const arr = [12, 3, 45, 7, 2];
arr.sort((a, b) => b - a);
console.log(arr); // [45, 12, 7, 3, 2]

无参数的大坑(错误示例)

复制代码
const arr = [10, 2, 30];
arr.sort(); 
console.log(arr); // [10, 2, 30] 按字符串比较,不是数字大小

2. 字符串数组排序

普通字母升序

复制代码
const words = ["banana", "apple", "cat"];
words.sort();
console.log(words); // ["apple", "banana", "cat"]

忽略大小写排序

复制代码
const words = ["Banana", "apple", "Cat"];
words.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));

中文排序(localeCompare)

复制代码
const names = ["张三", "李四", "王五"];
names.sort((a, b) => a.localeCompare(b, "zh-CN"));

3. 对象数组排序(工作最常用)

按数字字段排序(age)

复制代码
const list = [
  { name: "小明", age: 20 },
  { name: "小红", age: 16 },
  { name: "小刚", age: 22 }
];

// 年龄升序
list.sort((a, b) => a.age - b.age);
// 年龄降序
list.sort((a, b) => b.age - a.age);

按字符串字段排序(name)

复制代码
list.sort((a, b) => a.name.localeCompare(b.name));

按时间戳 / 日期排序

复制代码
const data = [
  { time: 1720000000 },
  { time: 1710000000 }
];
data.sort((a, b) => a.time - b.time);

4. 不修改原数组排序

sort() 会改变原数组,先复制一份再排序:

复制代码
const arr = [5, 1, 3];
// 方式1:展开运算符
const newArr = [...arr].sort((a, b) => a - b);
// 方式2:slice
const newArr2 = arr.slice().sort((a, b) => a - b);

5. 多级排序(先按 A,相等再按 B)

示例:先按分数降序,同分按年龄升序

复制代码
const stu = [
  { score: 90, age: 18 },
  { score: 95, age: 17 },
  { score: 90, age: 16 }
];
stu.sort((a, b) => {
  // 分数不等,先排分数
  if (b.score !== a.score) {
    return b.score - a.score;
  }
  // 分数相同,按年龄升序
  return a.age - b.age;
});

6. 倒序反转(reverse)

复制代码
const arr = [1, 2, 3];
arr.reverse(); // [3,2,1]

常见注意点

  1. 纯数字排序必须传 a-b / b-a,不能直接 sort ()
  2. 字符串、中文排序用 localeCompare
  3. sort 会改变原数组,不想改动先拷贝数组
  4. 浮点数同样适用 a - b 排序
  5. null/undefined 参与排序会排在前面

数组类型检测 4 种常用方案

1. Array.isArray ()【推荐,最标准】

专门判断是否为数组,兼容所有场景,区分数组、对象、类数组

复制代码
console.log(Array.isArray([])); // true
console.log(Array.isArray([1,2])); // true
console.log(Array.isArray({})); // false
console.log(Array.isArray("abc")); // false
console.log(Array.isArray(null)); // false
console.log(Array.isArray(new Array())); // true

// 类数组(arguments、DOM集合)返回 false
function fn(){
  console.log(Array.isArray(arguments)); // false
}

2. Object.prototype.toString.call ()【万能精准类型判断】

能精准区分所有内置类型,返回固定格式 [object 类型名]

复制代码
const getType = val => Object.prototype.toString.call(val);

console.log(getType([])); // "[object Array]"
console.log(getType(new Array())); // "[object Array]"
console.log(getType({})); // "[object Object]"
console.log(getType(null)); // "[object Null]"
console.log(getType(123)); // "[object Number]"

// 判断数组封装
const isArr = val => Object.prototype.toString.call(val) === '[object Array]';

3. instanceof Array【有缺陷,跨窗口 /iframe 失效】

原理:判断构造函数 Array 是否在实例原型链上

复制代码
[] instanceof Array; // true
new Array() instanceof Array; // true

// 缺陷:不同窗口的Array构造函数不是同一个,会返回false
const iframeArr = window.frames[0].Array();
console.log(iframeArr instanceof Array); // false

4. constructor【缺陷更多,可被篡改】

复制代码
const arr = [];
console.log(arr.constructor === Array); // true

// 缺点1:构造函数可被修改
arr.constructor = String;
console.log(arr.constructor === Array); // false

// 缺点2:跨iframe失效

类数组判断(不是数组,但可遍历)

argumentsdocument.querySelectorAll() 返回的 NodeList 特征:有 length、数字下标,没有数组方法 (map/sort)

复制代码
function isLikeArray(val) {
  if (!val) return false;
  return typeof val === 'object' && 'length' in val && !Array.isArray(val);
}

总结对比

表格

方法 优点 缺点 使用场景
Array.isArray 简洁、无坑、ES5+ 无法区分其他类型 日常判断数组首选
toString.call 精准识别所有内置类型 写法稍长 需要同时判断多种数据类型
instanceof 简单 跨 iframe 失效 单一页面简单场景
constructor 极简 可篡改、跨窗口失效 不推荐生产使用

通用工具函数

复制代码
// 判断是否为数组
const isArray = (val) => Array.isArray(val);

// 获取准确数据类型
const getDataType = (val) => {
  return Object.prototype.toString.call(val).slice(8, -1);
};
console.log(getDataType([])); // Array
console.log(getDataType({})); // Object
相关推荐
拳里剑气2 小时前
C++算法:链表
c++·算法·链表
凌波粒2 小时前
LeetCode--90.子集II(回溯算法)
数据结构·算法·leetcode
旖-旎2 小时前
《LeetCode 417 太平洋大西洋水流问题 FloodFill DFS 解法》
c++·算法·深度优先·力扣·floodfill
凌波粒2 小时前
LeetCode--46.全排列(回溯算法)
数据结构·算法·leetcode
2zcode2 小时前
项目文档:基于MATLAB语音信号变声算法设计与实现
算法·matlab·语音识别
指令集梦境2 小时前
图解:单调栈算法模板(Java语言)
java·开发语言·算法
生成论实验室2 小时前
自动驾驶:一个自主运动的系统
人工智能·算法·机器学习·语言模型·机器人·自动驾驶·安全架构
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2026.06.16 题目:3612. 字符串特殊符号处理
笔记·算法·leetcode
CoderYanger3 小时前
A.每日一题:2095. 删除链表的中间节点
java·数据结构·程序人生·leetcode·链表·面试·职场和发展