【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

相关推荐
User:你的影子1 分钟前
WPF ItemsControl 绑定
开发语言·前端·javascript
LFly_ice1 小时前
学习React-10-useTransition
前端·学习·react.js
知识分享小能手1 小时前
React学习教程,从入门到精通,React 构造函数(Constructor)完整语法知识点与案例详解(16)
前端·javascript·学习·react.js·架构·前端框架·vue
召摇1 小时前
NodeBB 深度解析:现代论坛系统的架构设计与实践指南
前端·javascript
flower_tomb2 小时前
对浏览器事件机制的理解
前端·javascript·vue.js
超人不会飛2 小时前
仿豆包 H5应用核心模板:用Vue快速复刻大模型对话体验
前端·javascript·vue.js
淮北也生橘122 小时前
Linux的V4L2视频框架学习笔记
linux·笔记·学习·音视频·嵌入式linux
程序张2 小时前
Vue3+Vite 现代化前端框架👊打破 Chrome 83 内核限制
前端·javascript·vue.js
Mintopia2 小时前
Next.js自建部署:Docker + PM2 + Nginx
前端·javascript·全栈
艾小码2 小时前
还在重复造轮子?3个Vue3组合函数让你开发效率翻倍!
前端·javascript·vue.js