区分普通对象和构造函数实例需看三点:创建方式(字面量或object.create vs new调用)、constructor及instanceof(plain.constructor===object,p.constructor===person且p instanceof person为true)、原型链({}.__proto__===object.prototype,p.__proto__===person.prototype)。

区分普通对象和构造函数创建的实例,核心看三点:创建方式、构造器归属、原型链结构。表面都是 {},但内部逻辑完全不同。
看创建方式和调用关键词
普通对象通常用字面量 {} 或 Object.create(null) 创建;而构造函数实例必须通过 new 调用生成。
-
const plain = {};→ 普通对象,没用new -
function Person() {}; const p = new Person();→ 构造函数实例 - 漏掉
new(如直接调用Person())会导致this指向全局或undefined,不是实例
查 constructor 和 instanceof
构造器信息能快速反映对象“出身”。
-
plain.constructor === Object返回true -
p.constructor === Person返回true(前提是没手动改过constructor) -
p instanceof Person为true;plain instanceof Person为false - 所有对象都满足
obj instanceof Object,所以它不能单独识别自定义类型,但可辅助验证
观察 __proto__ 和原型链归属
每个对象的 __proto__ 决定了它能继承什么,这是最底层的区分依据。
-
{}.__proto__ === Object.prototype→ 成立,是普通对象 -
p.__proto__ === Person.prototype→ 成立(未被篡改时),说明它是Person的实例 - 进一步验证:
p.__proto__.constructor === Person可回溯到原始构造函数 - 如果原型链最终只落到
Object.prototype,且中间没经过Array、Date等内置构造函数,则是“纯粹”的 plain object
用 Object.prototype.toString.call() 辅助判断
这个方法稳定,不受原型污染影响,适合排除内建类型。
-
Object.prototype.toString.call({})→"[object Object]" -
Object.prototype.toString.call(new Date())→"[object Date]" -
Object.prototype.toString.call(new Person())→ 仍是"[object Object]",无法直接看出是Person,但它能帮你确认不是Array、Function等特殊类型











