JavaScript中Object构造函数两种调用方式的实现原理探究
为什么
new Object({a:3})和Object({a:3})结果一致? 你猜的方向完全没错!Object之所以能同时支持构造函数调用(带new)和普通函数调用,核心就是内部做了调用方式的判断,然后分逻辑处理。下面详细拆解:
1. 核心判断:区分调用方式
Object内部会先判断当前是用new关键字调用,还是作为普通函数调用:
- 带
new调用时:this指向new关键字刚创建的空对象(也就是Object的实例),同时可以通过new.target检测到这是构造函数调用。 - 普通函数调用时:非严格模式下
this指向全局对象(浏览器里是window,Node.js是globalThis),严格模式下this是undefined,此时new.target为undefined。
2. 分场景的处理逻辑
不管哪种调用方式,Object的核心行为都是:如果传入的是对象/null/undefined,直接返回对应值;如果是原始值,返回对应的包装对象。具体分支如下:
情况1:带new调用(new Object({a:3}))
new关键字先创建一个空的Object实例,把它绑定为this。- 检查传入的参数:如果参数是一个对象(比如
{a:3}),Object会直接返回这个传入的对象,而不是一开始创建的空this对象。 - 如果传入的是原始值(比如
new Object(123)),则会把原始值包装成对应的包装对象(这里是Number {123})并返回。 - 如果没有参数(
new Object()),则返回一开始创建的空对象。
情况2:普通函数调用(Object({a:3}))
- 此时
this指向全局对象(或严格模式下的undefined),Object会忽略this,直接处理传入的参数。 - 和构造函数调用逻辑一致:传入对象就返回该对象,传入原始值就返回包装对象,无参数则返回空对象。
用伪代码模拟实现
你之前猜的逻辑很接近,这里给出更贴合规范的伪代码:
function Object(value) { // 检测是否是new调用 if (new.target !== undefined) { // 构造函数调用分支 if (value == null) { // 无参数/参数是null/undefined return this; } // 是对象直接返回,否则包装后返回 return typeof value === 'object' ? value : Object(value); } else { // 普通函数调用分支 if (value == null) { return {}; } return typeof value === 'object' ? value : Object(value); } }
规范层面的依据
根据ECMAScript规范,Object构造函数的内部实现包含两个关键方法:
[[Construct]]:当用new调用时触发,先创建新对象,再执行函数体,最后根据函数返回值决定返回新对象还是函数的返回结果。[[Call]]:当作为普通函数调用时触发,直接执行函数体并返回结果。
正是因为Object在两种调用方式下,对对象类型参数的处理都是直接返回该对象,所以你测试的两种写法最终得到的都是{a:3}。
内容的提问来源于stack exchange,提问作者Radu Szasz
相关产品推荐
相关产品推荐

