JavaScript中高效统计对象键/属性数量的方法

JavaScript中高效统计对象键/属性数量的方法

技术背景

在JavaScript里,标准的Object实现并不要求对象追踪其键/属性的数量。所以,要确定一个对象的大小,就需要显式或隐式地遍历其键。接下来为你介绍一些常用的实现方法。

实现步骤

1. 使用Object.keys()方法

1
Object.keys(obj).length;

这种方法会在内部遍历对象的键,生成一个临时数组,然后返回该数组的长度。

  • 优点:语法简洁易读,除了在不支持原生方法时需要一个垫片(shim)外,无需其他库或自定义代码。
  • 缺点:由于创建了数组,会带来一定的内存开销。

2. 基于库的解决方案

许多基于库的方法,像使用Underscore.js_.size(obj)_.keys(obj).length ,其实内部封装的也是for循环或者ES5Object.keys方法。

3. 优化for循环

1
2
var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

for循环中最慢的部分通常是.hasOwnProperty()调用,因为存在函数调用的开销。若确定没有代码扩展Object.prototype,可以跳过这个调用。

4. 使用Map对象

1
2
3
const map = new Map();
map.set("key", "value");
map.size;

Map对象会自行跟踪其大小,这种方式速度极快。

5. 包含非枚举属性的统计

1
Object.getOwnPropertyNames(myObject).length;

Object.getOwnPropertyNames方法可以统计对象的所有属性,包括非枚举属性。

6. 自定义对象属性统计

可以通过Object.defineProperty为对象添加length属性来统计键的数量。

1
2
3
4
5
6
Object.defineProperty(Object.prototype, "length", {
enumerable: false,
get: function() {
return Object.keys(this).length;
}
});

核心代码

以下是不同方法的核心代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 1. Object.keys()
const obj = {a: 1, b: 2};
console.log(Object.keys(obj).length);

// 2. 手动for循环
let size = 0;
for (let k in obj) {
size++;
}
console.log(size);

// 3. 使用Map
const map = new Map();
map.set('key1', 'value1');
map.set('key2', 'value2');
console.log(map.size);

// 4. 包含非枚举属性
var myObject = new Object();
Object.defineProperty(myObject, "nonEnumerableProp", {
enumerable: false
});
Object.defineProperty(myObject, "enumerableProp", {
enumerable: true
});
console.log(Object.getOwnPropertyNames(myObject).length);

// 5. 自定义length属性
Object.defineProperty(Object.prototype, "length", {
enumerable: false,
get: function() {
return Object.keys(this).length;
}
});
const myObj = {name: 'John', age: 30};
console.log(myObj.length);

最佳实践

  • 性能优先:如果追求极致性能,且可以控制对象类型,建议使用Map对象。
  • 代码简洁:对于大多数情况,使用Object.keys(obj).length是最简单的选择。
  • 兼容性:在旧浏览器中,需要添加Object.keys的垫片代码。

常见问题

1. Object.keys()方法在旧浏览器中不支持怎么办?

可以添加垫片代码:

1
2
3
4
5
6
7
8
9
10
11
12
if (!Object.keys) {
Object.keys = function (obj) {
var keys = [],
k;
for (k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
keys.push(k);
}
}
return keys;
};
}

2. 如何统计包含非枚举属性的对象大小?

使用Object.getOwnPropertyNames方法:

1
Object.getOwnPropertyNames(obj).length;

3. 函数作为对象属性时,Object.keys()会统计函数吗?

会。Object.keys()会统计对象的所有可枚举属性,包括函数。若不想统计函数,可以将函数单独放在一个对象中。


JavaScript中高效统计对象键/属性数量的方法
https://119291.xyz/posts/how-to-efficiently-count-keys-of-object-in-javascript/
作者
ww
发布于
2025年5月23日
许可协议