本文集中整理 JavaScript 中容易混淆的三组基础知识:数据类型、
for...in 与 for...of,以及 splice、slice 与 toSpliced。读完后可以根据遍历目标和是否修改原数组选择合适的写法。1. JavaScript 数据类型
JavaScript 的值可以分为原始值(primitive)和对象(object)。
1.1 七种原始类型
undefined
null
boolean
number
bigint
string
symbol
原始值不可变。所谓不可变,是指不能直接改变这个值本身;变量仍然可以重新赋值。
1.2 对象类型
除原始值外,其余值都属于对象,包括:
- 普通对象
Object
- 数组
Array
- 函数
Function
- 日期
Date
- 正则表达式
RegExp
Map、Set
Promise
数组和函数在类型体系上也是对象,但函数还具有可调用能力。
1.3 typeof 常见结果
判断数组应使用:
判断
null 应直接比较:1.4 number 的注意事项
JavaScript 的普通数字采用 IEEE 754 双精度浮点格式,因此:
需要精确处理货币时,常见做法是使用整数最小单位,例如把 10.25 元保存为 1025 分;超出安全整数范围时可考虑
bigint。number 与 bigint 不能直接混合运算:2. for...in 与 for...of
本章比较对象键遍历、可迭代值遍历和数组遍历三类场景。
2.1 for...in
for...in 遍历对象的可枚举字符串属性键,也可能包含原型链上的属性。现代代码优先使用
Object.hasOwn(obj, key),而不是直接调用 obj.hasOwnProperty(key),因为对象可能没有继承该方法,或存在同名属性。适合场景:
- 枚举普通对象的键;
- 需要处理属性名;
- 明确理解原型链和可枚举性。
2.2 for...of
for...of 遍历可迭代对象产生的值。常见可迭代对象:
Array
String
Map
Set
TypedArray
NodeList
- 自定义实现
[Symbol.iterator]的对象
2.3 为什么不推荐用 for...in 遍历数组
可能输出:
而且数组索引以字符串键出现,遍历顺序和数组值语义也不是
for...in 的设计重点。需要数组值:
需要索引和值:
需要支持
break、continue 或 await 时,for...of 通常比 .forEach() 更合适。3. splice、slice 与 toSpliced
本章从「splice:修改原数组」「slice:提取浅拷贝,不修改原数组」和「toSpliced:不修改原数组的增删改」等方面说明 splice、slice 与 toSpliced。
3.1 splice:修改原数组
签名:
返回被删除元素组成的新数组。
3.2 slice:提取浅拷贝,不修改原数组
签名:
区间为左闭右开
[start, end)。“浅拷贝”意味着嵌套对象仍然共享引用:
3.3 toSpliced:不修改原数组的增删改
现代 JavaScript 提供
toSpliced:在 React 等强调不可变更新的场景中,
toSpliced 或展开运算符通常比直接 splice 更安全。4. 快速选择
- 遍历对象键:
Object.keys()、Object.entries()或谨慎使用for...in。
- 遍历数组和集合值:
for...of。
- 需要索引:普通
for、entries()或.forEach()。
- 修改原数组并插入、删除、替换:
splice。
- 截取子数组且不改原数组:
slice。
- 想使用
splice的语义但保持不可变:toSpliced。
5. 常见易错点
typeof null返回"object",不能用它判断null。
- 数组也是对象,判断数组使用
Array.isArray。
for...in得到键,for...of得到迭代值。
for...in可能遍历到继承的可枚举属性。
splice会修改原数组,slice不会。
slice是浅拷贝,不会递归复制嵌套对象。
6. 总结
JavaScript 中应先区分值的类型,再根据目标选择遍历和数组操作:对象键适合
Object.keys()、Object.entries() 或谨慎使用 for...in,可迭代值适合 for...of;需要原地修改数组时使用 splice,需要新数组时使用 slice 或 toSpliced。