当前位置: 首页 > java >正文

【javascript】new.target 学习笔记

new.target

new.target 是一个元属性(meta property),在ECMAScript 2015 (ES6) 中引入,用于检测函数是否通过 new 关键字调用。简单来说,当一个函数用 new 关键字调用时,new.target 会指向这个函数本身;如果函数是直接调用,new.target 的值则为 undefined

function Foo() {console.log('new.target',new.target)console.log('new.target.prototype',new.target.prototype)if (!new.target) {throw new TypeError("calling Foo constructor without new is invalid");}
}try {new Foo();Foo();
} catch (e) {console.log(e);// Expected output: TypeError: calling Foo constructor without new is invalid
}
// 输出:
/*
"new.target" function Foo() {console.log('new.target',new.target)console.log('new.target.prototype',new.target.prototype)if (!new.target) {throw new TypeError("calling Foo constructor without new is invalid");}
}"new.target.prototype" Object {  }*//*"new.target" undefinedTypeError: Cannot read properties of undefined (reading 'prototype')*/

new.target 保证是一个可构造的函数值或 undefined。

  • 在类构造函数中,它指向 new 调用的类,这可能是当前构造函数的子类,因为子类通过 super() 传递调用了父类的构造函数。

    在父类的构造函数里,new.target 并不等于父类本身,而是“真正被 new 的那个类”——往往正是它的某个子类。因为子类在构造时要先 super(),于是父类构造函数的 new.target 就指向了子类。

    class Animal{constructor() {console.log('Animal -> new.target.name:', new.target.name);}
    }
    class Dog extends Animal{constructor() {super();console.log('Dog -> new.target.name:', new.target.name);}
    }
    class toyDog extends Dog{constructor() {super();console.log('ToyDog -> new.target.name:', new.target.name);      }
    }
    new Dog();
    // Animal -> new.target.name: Dog
    // Dog -> new.target.name: Dog
    console.log('----------------');
    new toyDog();        
    // Animal -> new.target.name: toyDog
    // Dog -> new.target.name: toyDog
    // ToyDog -> new.target.name: toyDog
    
  • 在普通函数中,如果函数是直接通过 new 构造的,则 new.target 指向函数本身。如果函数不是通过 new 调用的,则 new.targetundefined。函数可以被用作 extends 的基类,这种情况下 new.target 可能指向子类。

    function Foo(msg) {console.log(msg, '--new.target =', new.target);
    }
    // 通过 `new` 构造的,则 `new.target` 指向函数本身
    new Foo('new Foo');
    /* 输出:new Foo --new.target = ƒ Foo(msg) {console.log(msg, '--new.target =', new.target);
    } */
    // 不是通过 `new` 调用的,则 `new.target` 是 `undefined`
    Foo('call Foo');  
    /* 输出:call Foo --new.target = undefined */// 函数可以被用作 `extends` 的基类,这种情况下 `new.target` 可能指向子类。
    class Bar extends Foo {constructor() {super('new Bar');}
    }
    new Bar();
    /* 输出:new Bar --new.target = class Bar extends Foo {constructor() {super('new Bar');}
    }  */     
    
  • 如果构造函数(类或者函数)是通过 Reflect.construct() 调用的,那么 new.target 指向作为 newTarget 传递的值(默认为 target)。

    function One(name) {this.name = name;console.log('One -> new.target.name:', new.target.name);
    }
    const obj=Reflect.construct(One, ['aa'], Array);
    console.log(obj); // 输出:Array {name: 'aa'}
    console.log('obj instanceof One:', obj instanceof One); // 输出:obj instanceof One: false
    console.log('obj instanceof Array:', obj instanceof Array); // 输出:obj instanceof Array: true
    
  • 在箭头函数中,new.target 是从周围的作用域继承的。如果箭头函数不是在另一个具有 new.target 绑定的类或函数中定义的,则会抛出语法错误。

    class A {constructor() {const arrow = () => console.log('new.target →', new.target);arrow();          // 箭头函数继承自构造函数作用域}
    }
    class B extends A {}
    new B();
    //输出:new.target → class B extends A {}
    
    // 在全局作用域里
    const arrow = () => {console.log(new.target); // 报错:ReferenceError
    };
    arrow();
    //输出报错:Uncaught SyntaxError: new.target expression is not allowed here
    
  • 在静态初始化块中,new.targetundefined

    class WithStatic {static {console.log('Static block new.target:', new.target); // undefined}
    }
    new WithStatic();
    // 输出:Static block new.target: undefined
    

参考:

MDN new.target

http://www.xdnf.cn/news/16799.html

相关文章:

  • 【2025/07/31】GitHub 今日热门项目
  • DAY16-结构体
  • linux如何将两份hdmi edid合并
  • system.conf linux用于启动和管理系统进程的初始化系统和服务管理器的配置文件
  • WEditor:高效的移动端UI自动化脚本可视化编辑器
  • 【云故事探索】NO.16:阿里云弹性计算加速精准学 AI 教育普惠落地
  • 力扣 Pandas 挑战(6)---数据合并
  • 基于SpringBoot和SpringAI框架实践
  • Google政策大更新:影响金融,Ai应用,社交,新闻等所有类别App
  • 【科研绘图系列】R语言绘制线性相关性
  • 算法训练营day37 动态规划⑤ 完全背包 518. 零钱兑换 II、 377. 组合总和 Ⅳ、70. 爬楼梯 (进阶)
  • 排序的演进:从机械齿轮到领域专用芯片加速器的全面综述
  • 最新PS 2025安装包下载与安装教程(Adobe Photoshop 2025 )
  • 【数据结构初阶】--二叉树(六)
  • 乱删文件,电脑不能开机,怎么办
  • 【C语言】深度剖析指针(三):回调机制、通用排序与数组指针逻辑
  • DeepSeek笔记(三):结合Flask实现以WEB方式访问本地部署的DeepSeek-R1模型
  • opencv解迷宫
  • 是德科技的BenchVue和纳米软件的ATECLOUD有哪些区别?
  • RabbitMQ 的死信队列完整指南 (With Spring Boot)
  • 【13】大恒相机SDK C#开发 —— Fom1中实时处理的8个图像 实时显示在Form2界面的 pictureBox中
  • 多架构镜像整合全攻略:在Docker中实现单一镜像支持同时支持amd64和arm64架构
  • 贝锐蒲公英X4 Pro 5G新品路由器:异地组网+8网口+双频WiFi全都有
  • 网站域名备案和服务器有关系吗
  • 【源力觉醒 创作者计划】文心大模型开源:从封闭研发到生态共建的转折点
  • 设计模式:命令模式 Command
  • 【Java23种设计模式】:模板方法模式
  • Windows 11下IDEA中使用git突然变得卡慢及解决办法
  • UI测试平台TestComplete如何实现从Git到Jenkins的持续测试
  • 【AI大模型】披着羊皮的狼--自动化生成越狱提示的系统(ReNeLLM)