Reflect API 将数组视为普通对象,支持通过 get/set/deleteProperty 安全操作索引和 length,ownKeys/has 准确反映自有属性,但不提供 push/pop 等数组特有方法,需用 Reflect.apply 调用;与 Proxy 配合时仍保持数组行为一致性。

Reflect API 本身不提供专门针对数组的特殊操作方法,它对数组的处理完全遵循 JavaScript 的通用对象语义——也就是说,数组在 Reflect 看来就是普通对象,其索引属性、length 属性、原型链行为都按标准规范处理。这种“无差别对待”恰恰是它健壮性的来源,但需要你清楚边界在哪里。
Reflect.get/set/deleteProperty 对数组索引和 length 的操作是合法且有效的
你可以用 Reflect 安全读写数组元素或 length,它会尊重数组的内部约束:
- 读取索引:Reflect.get(arr, '0')、Reflect.get(arr, 0) 都能取到首项(字符串/数字键均可,数组自动转换)
- 设置索引:Reflect.set(arr, 2, 'x') 成功返回 true;若 arr 被冻结(Object.freeze),则返回 false,不会抛错
- 修改 length:Reflect.set(arr, 'length', 1) 可截断数组,行为与 arr.length = 1 一致;若 length 设为非整数或负值,Reflect.set 返回 false,不触发异常
- 删除元素:Reflect.deleteProperty(arr, '1') 删除索引 1 的元素,返回 true;但不会改变 length,也不会触发数组的“稀疏性”重排逻辑(这和 delete arr[1] 行为相同)
Reflect.ownKeys 和 Reflect.has 能准确反映数组的自有结构
这两个方法对数组特别实用:
- Reflect.ownKeys(arr) 返回所有自有属性键(包括数字索引、length、以及手动添加的字符串属性),顺序与 for...in 一致但不含原型属性,比 Object.keys 更完整
- Reflect.has(arr, '2') 判断索引 2 是否为 arr 的自有属性(即是否已赋值),不会误判 undefined 元素;而 arr[2] !== undefined 在值为 undefined 时会返回 false,语义不同
注意:Reflect 不模拟数组方法,也不拦截 push/pop 等变异操作
数组的内置方法(如 push、pop、splice)属于 Array.prototype 上的函数调用,Reflect 没有对应方法去“反射式调用”它们。如果你需要动态调用这些方法,得用 Reflect.apply:
- Reflect.apply(Array.prototype.push, arr, ['a', 'b']) 等价于 arr.push('a', 'b')
- Reflect.apply(Array.prototype.slice, arr, [1, 3]) 等价于 arr.slice(1, 3)
- 但这只是函数调用转发,不改变原语义,也不提供额外保护
与 Proxy 配合时,数组行为保持可预测
当你用 Proxy 包裹数组,并在 trap 中用 Reflect 方法转发时,数组的特殊行为(如 length 自动更新、索引赋值触发 length 变更)仍被保留:
- 在 set trap 中调用 Reflect.set(target, '3', 'd'),target.length 会自动变为 4
- 在 get trap 中调用 Reflect.get(target, 'length'),返回的是实时计算值
- 关键点:必须传入 receiver(通常是 proxy 本身),否则 getter 中的 this 可能指向错误

















