前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版
首页程序员面试题库new.target 含义与箭头函数
JavaScript函数与作用域

new.target 是什么?在箭头函数里读它会得到什么?

new.target 告诉你当前函数是不是通过 new 调用的。用 new 调用时,它等于 new 后面写的那个构造函数;直接调用时是 undefined。箭头函数没有自己的 new.target,和 this 一样取外层函数的值。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#函数与作用域
先看核心答案读代码示例
理解线索

三种情况下的 `new.target`

  1. 普通调用Foo() 直接调用,函数里的 new.target 是 undefined
  2. new 调用new Foo() 时是 Foo,可以用来确认调用方式
  3. 继承new Circle() 走到父类 Shape 的构造函数时,读到的仍是 Circle

new.target 只能写在函数里。写在脚本或模块的顶层会直接报语法错误,写在顶层的箭头函数里也一样。

核心回答

先记住这个答案

new.target 是 ES6 加的一个特殊语法,用来判断函数是怎么被调用的。用 new Foo() 调用时,Foo 里的 new.target 就是 Foo 这个函数本身;直接 Foo() 调用时,它是 undefined。在类的继承中,new Circle() 会先执行父类 Shape 的构造函数,这时 Shape 里读到的 new.target 是 Circle,也就是最初被 new 的那个类。箭头函数没有自己的 new.target,在箭头函数里读到的是包着它的那个普通函数的值。

  • new 调用时指向被 new 的构造函数
  • 普通调用时是 undefined
  • 子类实例化时,父类构造函数里读到的是子类
  • 箭头函数读的是外层函数的 new.target

三种情况跑一遍

普通函数的两种调用方式,加上类继承和箭头函数,放在一起看。

普通调用、new 调用、继承JavaScript
function Legacy() {
  console.log(new.target === Legacy ? 'new 调用' : '普通调用')
}
Legacy()
new Legacy()

class Shape {
  constructor() {
    const who = () => new.target.name // 箭头函数读外层 constructor 的 new.target
    console.log(who())
  }
}
class Circle extends Shape {}
new Shape()
new Circle() // 父类构造函数里看到的是 Circle
查看输出与解释
普通调用
new 调用
Shape
Circle

new Circle() 时,Circle 没写构造函数,默认构造函数会调用 super(),于是执行了 Shape 的 constructor。这时 new.target 没有变成 Shape,而是一路保持为 Circle。箭头函数 who 自己没有 new.target,读到的就是这个 constructor 的值。 为什么要一路保持为子类?因为实例的原型要用 new.target.prototype 来设置。new Circle() 创建的实例原型必须是 Circle.prototype,才能用上子类的方法,所以父类构造函数得知道「最终要造的是谁」。

实际能拿它做什么

new.target 最常见的用法有两个,都是在构造函数开头加一个判断。

强制必须用 new,或者自动补上
老式构造函数忘写 new 时,this 会指向全局对象或 undefined,属性就写错地方了。可以在开头判断 if (!new.target) return new Legacy(...arguments),漏写 new 也能得到正确的实例。也可以直接抛错,提醒调用方。class 不需要这么做,不写 new 调用 class 本来就会抛 TypeError。
实现抽象基类
JavaScript 没有 abstract 关键字,可以在父类构造函数里判断 if (new.target === Shape) throw new TypeError('Shape 不能直接实例化')。直接 new Shape() 会报错,new Circle() 时 new.target 是 Circle,正常通过。TypeScript 的 abstract class 只在编译时检查,编译后这个限制就没了,需要运行时也拦住时就用这个写法。
回答前,多想一步

容易答错的地方

以为父类构造函数里的 new.target 是父类
继承链上所有构造函数读到的都是最初被 new 的那个类。想在父类里判断「是不是直接 new 我」,要比较 new.target === Shape,而不是只看它是否存在。
以为 this instanceof Foo 和 new.target 等价
this instanceof Foo 能被骗过:Foo.call(Object.create(Foo.prototype)) 是普通调用,但 this 满足 instanceof。new.target 由调用方式决定,这种情况下它是 undefined,判断更准确。
试着用自己的话回答

面试官还会怎么问?

在对象方法里读 new.target 会怎样?

不会报错,但永远是 undefined。方法简写本身不能被 new,也就不存在「被 new 调用」的时候。

Reflect.construct 和 new.target 有什么关系?

Reflect.construct(Target, args, NewTarget) 的第三个参数就是用来指定 new.target 的。执行 Target 的代码,但函数里读到的 new.target 是 NewTarget,实例的原型也取 NewTarget.prototype。在没有 class 语法时,想让老式构造函数正确继承内置类,就要靠它。

为什么箭头函数不能 new,却能读 new.target?

箭头函数不能当构造函数,所以它没有属于自己的 new.target。它读到的是外层普通函数的值,就像它读 this 和 arguments 一样。外层没有普通函数、箭头函数直接写在顶层时,读 new.target 是语法错误。

从一道题,走向一组知识

把知识连起来

函数与作用域

对象里写 fn() {} 和 fn: function () {} 有区别吗?

对象方法简写不能被 new,所以在方法里读 new.target 永远是 undefined。

函数与作用域

obj.fn?.() 怎么用?用可选链调用方法,this 会丢吗?

示例里常写 new.target?.name 防止普通调用时读 undefined 的属性报错,用的就是可选链。

参考资料

  • JavaScript:函数与作用域参考资料

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

本题目录
  1. 先记住这个答案
  2. 三种情况跑一遍
  3. 实际能拿它做什么
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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