目标
知道什么是数组
会创建数组
知道如何访问和遍历数组
知道如何对数组元素进行新增、修改、删除、排序
能够独立完成经典的数组排序程序------冒泡排序和插入排序
一、数组的概念
问:什么是数组呢?
答:数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的方式。
二、创建数组
++创建数组++ 的两种常见方式的用法:
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';
}
- ECMAScript6 新增的一种循环方式,也是for循环的变体;
- 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)
参数:
item:当前遍历元素index:当前元素下标(可选)arr:原数组本身(可选)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((累加器, 当前项, 索引, 原数组) => {
处理逻辑
}, 初始值)
四个参数逐个解释:
- 累加器 res(第一个参数) 保存上一次循环拼接好的字符串,每一轮循环都会更新。
- 当前项 item(第二个参数) 数组现在遍历到的那一个元素。
- 索引 index(第三个,可选) 当前元素下标,0、1、2......
- 原数组 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('分隔符')两者互为反向操作。
常见小坑
-
字符串首尾有分隔符,会出现空元素
let str = ",a,b,";
console.log(str.split(",")); // ["", "a", "b", ""] -
连续分隔符也会产生空位
"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 + 扩展符 | ❌ 不改变 | 截取拼接删除 | 新数组 |
四、常见坑
-
delete arr[index]不推荐 只会清空对应位置为 empty,数组长度不变,产生空位let arr = [1,2,3];
delete arr[1];
console.log(arr); // [1, empty, 3]
console.log(arr.length); // 3 -
splice 传负数下标会从尾部倒数截取,容易删错
-
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 | 全部匹配元素数组 | 取出所有符合条件数据 | ✅ |
六、常用场景示例
-
简单数字 / 字符串判断有无
const arr = ['a','b','c'];
if(arr.includes('b')){
console.log('存在');
} -
对象数组找一条数据
const user = list.find(v => v.id === 2);
if(user){
console.log('找到用户', user);
} -
判断对象是否存在
if(list.some(v => v.name === '张三')){
console.log('有张三');
} -
取出所有符合条件数据
const bigNums = [1,2,10,20].filter(v => v > 5);
小坑提醒
-
indexOf / includes匹配引用类型(对象、数组)永远返回 - 1/false,因为地址不同const arr = [{a:1}];
console.log(arr.includes({a:1})); // false -
查找对象一律用
find / findIndex / some / filter
数组映射(Array Map
数组映射核心方法:map(),作用是遍历数组,对每个元素执行处理,返回长度相同的新数组,不修改原数组。
一、JavaScript Array.map ()
语法
const newArr = 原数组.map((item, index, arr) => {
// 处理逻辑,必须return返回新元素
return 处理后的值
})
参数说明:
item:当前遍历元素(必选)index:当前元素下标(可选)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()
特性
- 原地排序:直接修改原数组
- 无参数时:把元素转字符串,按 Unicode 编码排序(数字会出错)
- 接收回调函数
(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]
常见注意点
- 纯数字排序必须传
a-b/b-a,不能直接 sort () - 字符串、中文排序用
localeCompare - sort 会改变原数组,不想改动先拷贝数组
- 浮点数同样适用
a - b排序 - 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失效
类数组判断(不是数组,但可遍历)
如 arguments、document.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