最可靠的方式是先用Object.prototype.toString.call()判断是否为[object Object],再检查原型链顶端是否为Object.prototype或null。

判断一个值是否为“普通对象”(即通过 {} 或 new Object() 创建的、不带自定义原型或特殊内部标签的对象),最可靠的方式是结合 Object.prototype.toString.call() 与原型检查。
使用 toString 判断内置对象类型
Object.prototype.toString 是最权威的类型检测手段,能准确区分原生对象、数组、日期、正则等:
-
Object.prototype.toString.call({}) === '[object Object]'→ ✅ 普通对象 -
Object.prototype.toString.call([]) === '[object Array]'→ ❌ 不是普通对象 -
Object.prototype.toString.call(new Date()) === '[object Date]'→ ❌ -
Object.prototype.toString.call(null)或undefined会返回对应字符串,需先做存在性判断
排除非普通对象:检查原型链起点
仅靠 [object Object] 不够,因为用户可能手动设置原型为 Object.prototype,或使用 Object.create(null)(它也满足 toString 条件,但不是“普通对象”):
-
Object.create(null)的toString结果仍是'[object Object]',但它没有继承Object.prototype上的方法(如hasOwnProperty) - 真正的普通对象,其原型链顶端必须是
Object.prototype,即Object.getPrototypeOf(obj) === Object.prototype(对直接创建的对象成立) - 更稳妥的做法是:检查
obj.constructor === Object且obj instanceof Object,但注意构造函数可被篡改,所以优先依赖原型链
推荐的可靠实现
综合以上,一个健壮的判断函数如下:
立即学习“Java免费学习笔记(深入)”;
function isPlainObject(obj) {
if (obj === null || typeof obj !== 'object') return false;
if (Object.prototype.toString.call(obj) !== '[object Object]') return false;
const proto = Object.getPrototypeOf(obj);
return proto === null || proto === Object.prototype;
}
说明:
- 先排除
null和非对象类型 - 用
toString排除非Object实例(如数组、Map、自定义类实例) - 最后验证原型是否为
Object.prototype或null(Object.create(null)的情况需明确排除,所以这里proto === null是允许的,但如果你只想要“有Object.prototype作为直接原型”的对象,就只保留proto === Object.prototype)
注意边界情况
以下值均不是普通对象:
-
Object.create(null)(无原型) -
new Date()、/regex/、new Map()(toString返回不同标签) - 函数(
typeof fn === 'function',已由第一行拦截) - ES6 类实例(
toString返回[object Object],但原型是类的prototype,不等于Object.prototype)










