前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库构造函数 return 对象或原始值时 new 的结果
JavaScript对象与原型

构造函数返回对象或原始值时,new 最后会得到什么?

普通构造函数返回对象或函数时,new 会交出这个返回值;返回数字、字符串、null 等原始值时,仍得到原本创建的 this。派生类有额外限制,不能显式返回非对象且非 undefined 的值。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#对象与原型
先看核心答案读代码示例
理解线索

`new` 怎样选择结果

  1. 默认实例普通构造函数没有返回对象时,new 交出原本的 this
  2. 返回对象返回非 null 对象或函数,就用它替换默认实例
  3. 派生类限制显式返回非对象且非 undefined 的值会抛 TypeError

返回外部对象后,写在原本 this 上的属性不会自动搬过去,instanceof 也可能变成 false。

核心回答

先记住这个答案

普通构造函数执行时,new 先准备一个实例,让函数里的 this 指向它。函数结束后,如果显式返回的是对象或函数,new 就交出这个返回值;没有返回值,或返回数字、字符串、null 等原始值,就交出原先的实例。类也能返回对象,但派生类对原始返回值有额外限制,不能照搬普通函数的规则。

  • 返回对象或函数会替换 new 创建的实例
  • 普通构造函数返回原始值会被忽略
  • null 是原始值,不会替换实例
  • 派生类显式返回其他原始值会抛错

换个返回值,结果就变了

最容易记错的是 null。对它使用 typeof 虽然得到 'object',它仍是原始值,不会替换实例。函数则相反,typeof 是 'function',但它属于对象,可以替换实例。

对象会替换,原始值不会JavaScript
function Create(kind) {
  this.fromThis = true
  if (kind === 'object') return { fromReturn: true }
  if (kind === 'function') return function returned() {}
  return null // 原始值,被忽略
}
const a = new Create('object')
const b = new Create('function')
const c = new Create('null')
console.log(a.fromThis, a.fromReturn)
console.log(typeof b, b instanceof Create)
console.log(c.fromThis, c instanceof Create)
查看输出与解释
undefined true
function false
true true

a 是函数返回的对象,原先写在 this 上的 fromThis 没跟过去。b 是函数,原型链也不是 Create.prototype 那条,所以这里的 instanceof 是 false。c 返回了 null,实际拿到的仍是默认实例。把 null 换成 0、'hello' 或 false,普通构造函数的结果也一样。

返回已有对象,调用方会看到什么

有人会利用这条规则做单例:第二次调用构造函数时直接返回上一次创建的对象。它确实能工作,但调用方看到的是缓存对象,这一次传入的参数可能根本不会生效。

第二次调用复用第一次的实例JavaScript
let cached
function Config(options) {
  if (cached) return cached // 替换这次 new 创建的实例
  this.options = options
  cached = this
}
const first = new Config({ theme: 'dark' })
const second = new Config({ theme: 'light' })
console.log(first === second)
console.log(second.options.theme)
查看输出与解释
true
dark

第二次 new 已经准备了临时实例,但构造函数返回 cached 后,它就被丢弃了。第二次的选项没有覆盖第一次的配置。更要小心的是,返回值可以是任意对象;如果它不是由这个构造函数创建的,instanceof Config 可能是 false。业务代码里若需要复用对象,明确写一个工厂函数或模块级缓存,通常比让 new 暗中复用更容易读懂。

派生类为什么要单独记

普通 class 的基类构造器可以返回对象来替换实例,返回原始值则被忽略。派生类不同:显式返回对象是允许的,甚至能跳过 super();但是得到的只是那个对象,不会自动带上父类和子类的实例字段。显式返回数字、字符串、null 等非对象且非 undefined 的值会抛 TypeError。返回 undefined 不算替换实例,仍须先调用 super() 才能正常结束。

比如 class Child extends Parent { constructor() { return { x: 1 } } } 能构造,但返回的是普通对象。语法里写了 extends,不代表结果一定满足 instanceof Child。如果在返回对象之前读取 this,却没有调用 super(),又会触发初始化错误。面试问到类时,把「能不能替换返回值」和「什么时候能访问 this」分开解释。

回答前,多想一步

容易答错的地方

把 null 当成对象返回值
typeof null 的历史结果是 'object',但语言规范把 null 归在原始值里。普通构造函数返回它,new 得到的仍是默认实例。判断是否会替换实例,要看返回值是否为非 null 的对象或函数。
以为返回对象后,this 上的属性也会保留
两个对象不会自动合并。返回 { id: 1 } 后,之前写到 this.name 的值只留在被丢弃的实例上。只有返回的对象本身就是那个 this,属性才会保留。
把派生类和普通函数混为一谈
普通函数返回 0 会被忽略;派生类构造器显式返回 0 会抛 TypeError。派生类没有写构造器时,引擎会处理好 super(),不要因此误以为所有子类都得手写构造器。
试着用自己的话回答

面试官还会怎么问?

返回函数时,new 的结果能调用吗?

能。函数也是对象,所以会替换默认实例。拿到的值就是那个可调用函数,除非另行设置原型链,否则它不是原构造函数的实例。

箭头函数能用 new 吗?

不能。箭头函数没有构造能力,new (() => {}) 会抛 TypeError。返回对象的规则只在目标本身能够作为构造函数时才有机会执行。

new.target 能判断结果有没有被替换吗?

不能。new.target 表示这次构造由哪个构造器发起,不会因为最终返回了别的对象就改变。要确认结果的属性和原型,得直接检查返回对象本身。

从一道题,走向一组知识

把知识连起来

对象与原型

在 ES6 class 的构造器中必须先调用 super() 吗?为什么?

派生类若直接返回对象可以跳过 super(),但读取 this 前仍得先初始化。

对象与原型

给 writable 为 false 的属性赋值,严格模式和非严格模式分别会怎样?

返回一个已有对象时,能否改它的属性还取决于属性的 writable 描述符。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • new

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 换个返回值,结果就变了
  3. 返回已有对象,调用方会看到什么
  4. 派生类为什么要单独记
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑