【javascript】new.target 学习笔记

new.target

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

javascript 复制代码
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" undefined
 TypeError: Cannot read properties of undefined (reading 'prototype')
 */

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

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

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

    javascript 复制代码
    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 可能指向子类。

    javascript 复制代码
    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)。

    javascript 复制代码
    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 绑定的类或函数中定义的,则会抛出语法错误。

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

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

参考:

MDN new.target

相关推荐
一块plus9 分钟前
创造 Solidity、提出 Web3 的他回来了!Gavin Wood 这次将带领波卡走向何处?
javascript·后端·面试
山中月侣15 分钟前
Java多线程编程——基础篇
java·开发语言·经验分享·笔记·学习方法
老虎062720 分钟前
JavaWeb前端03(Ajax概念及在前端开发时应用)
前端·javascript·ajax
小鸡脚来咯40 分钟前
react速成
前端·javascript·react.js
剽悍一小兔1 小时前
React15.x版本 子组件调用父组件的方法,从props中拿的,这个方法里面有个setState,结果调用报错
前端·javascript·react.js
神笔码农nice1 小时前
VUE从入门到精通二:ref、reactive、computed计算属性、watch监听、组件之间的通信
前端·javascript·vue.js
小眼睛FPGA1 小时前
【盘古100Pro+开发板实验例程】FPGA学习 | gamma 变化 | 图像实验指导手册
科技·学习·ai·fpga开发·fpga
Zayn1 小时前
JavaScript 小数精度问题
前端·javascript
Maxkim1 小时前
🐳 前端工程师的后端小实验:Docker + Sequelize 玩转 MySQL API 🚀
javascript·后端
subuq2 小时前
Web3.0 时代的电商系统:区块链如何解决信任与溯源问题?
大数据·网络·学习