You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何自定义Array.prototype方法会出现在for...in循环,原生方法却不会?

问题:为何自定义Array原型方法会被for...in遍历到,而原生方法不会?

我为Array原型添加了如下方法:

Array.prototype.intersection = function(other) { return this.filter(x => other.indexOf(x) >= 0);}

随后我对数组进行遍历,示例如下:

a = [1, 2, 3]
// 输出: (3) [1, 2, 3]
for (let j in a) console.log(j)
// 输出:
// VM30274:1 0
// VM30274:1 1
// VM30274:1 2
// VM30274:1 intersection
// undefined

根据Object.keys方法的定义:

Object.keys() returns an array whose elements are strings corresponding to the enumerable string-keyed property names found directly upon object. This is the same as iterating with a for...in loop, except that a for...in loop enumerates properties in the prototype chain as well. The order of the array returned by Object.keys() is the same as that provided by a for...in loop.

我理解intersection出现在遍历结果中的原因,也知道应使用keys()等方式遍历,但疑惑为何只有intersection被枚举,而push、pop等其他Array原型方法却没有?原生方法是否有特殊处理?


核心原因就是属性的可枚举性(enumerable)。

你直接给Array.prototype添加的方法,默认是**可枚举(enumerable: true)**的,所以会被for...in遍历到原型链上的这个属性。

而JS的原生数组方法(比如push、pop、shift这些),在定义的时候被设置成了不可枚举(enumerable: false)。你可以用Object.getOwnPropertyDescriptor验证一下:

// 查看自定义方法的属性描述
console.log(Object.getOwnPropertyDescriptor(Array.prototype, 'intersection'));
// 输出大概是: { value: ƒ, writable: true, enumerable: true, configurable: true }

// 查看原生push方法的属性描述
console.log(Object.getOwnPropertyDescriptor(Array.prototype, 'push'));
// 输出大概是: { value: ƒ, writable: true, enumerable: false, configurable: true }

如果想让你自定义的原型方法也不被for...in遍历到,可以用Object.defineProperty来定义,手动把enumerable设为false:

Object.defineProperty(Array.prototype, 'intersection', {
  value: function(other) {
    return this.filter(x => other.indexOf(x) >= 0);
  },
  enumerable: false, // 关键:设置为不可枚举
  writable: true,
  configurable: true
});

这样再用for...in遍历数组,就不会出现intersection了。

内容的提问来源于stack exchange,提问作者russell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:02:43