Cette page a été traduite à partir de l'anglais par la communauté.Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.
Reflect.construct()
Baseline Widely available
Cette fonctionnalité est bien établie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis septembre 2016.
La méthode statiqueReflect.construct() agit comme l'opérateurnew sous la forme d'une fonction. Elle est équivalente ànew cible(...args) et permet d'indiquer une valeur différente pournew.target.
Dans cet article
Exemple interactif
function func1(a, b, c) { this.sum = a + b + c;}const args = [1, 2, 3];const object1 = new func1(...args);const object2 = Reflect.construct(func1, args);console.log(object2.sum);// Expected output: 6console.log(object1.sum);// Expected output: 6Syntaxe
Reflect.construct(cible, listeArguments)Reflect.construct(cible, listeArguments, nouvelleCible)Paramètres
cibleLa fonction cible à appeler.
listeArgumentsUn objetsemblable à un tableau définissant les arguments à passer à
ciblelors de l'appel.nouvelleCibleFacultatifLa valeur de l'expression
new.targetpourcible.cibleindique lalogique d'initialisation de l'objet, tandis quenouvelleCible.prototypeindique leprototype de l'objet construit.
Valeur de retour
Une nouvelle instance de la cible indiquée, créée en l'appelant comme un constructeur (ou en appelantnouvelleCible si elle est fournie) avec les arguments fournis.
Exceptions levées
TypeErrorLevée si
cibleounouvelleCiblene sont pas des constructeurs, ou silisteArgumentsn'est pas un objet.
Description
Reflect.construct() fournit la sémantique réflective d'un appel à un constructeur. Autrement dit,Reflect.construct(cible, listeArguments, nouvelleCible) est sémantiquement équivalent à :
new cible(...listeArguments);Quand on utilise l'opérateurnew,cibleetnouvelleCible sont toujours les mêmes constructeurs.Reflect.construct() permet quant à elle de passer une valeur différente pournew.target. Conceptuellement,nouvelleCible est la fonction sur laquellenew est appelé etnouvelleCible.prototype devient le prototype de l'objet construit, tandis quecible est le constructeur effectivement exécuté pour l'initialisation de l'objet. On peut par exemple avoir une valeurnew.target différente du constructeur exécuté pour l'héritage de classe :
class A { constructor() { console.log(new.target.name); }}class B extends A {}new B(); // "B"Reflect.construct() permet d'invoquer un constructeur avec un nombre variable d'arguments (ce qui est également possible lors d'un appel à un constructeur normal grâce àla syntaxe de décomposition).
const obj = new Toto(...args);const obj = Reflect.construct(Toto, args);Reflect.construct() invoquela méthode interne[[Construct]] decible.
Exemples
>UtiliserReflect.construct()
const d = Reflect.construct(Date, [1776, 6, 4]);d instanceof Date; // trued.getFullYear(); // 1776Utiliser le paramètrenouvelleCible
Si le paramètrenouvelleCible est utilisé, il modifiera la valeur denew.target dans le constructeur. L'objet ainsi construit sera une instance denouvelleCible, pas decible.
function ClasseUne() { console.log("ClasseUne exécutée"); console.log(`new.target vaut ${new.target.name}`);}function AutreClasse() { console.log("AutreClasse exécutée"); console.log(`new.target vaut ${new.target.name}`);}const obj1 = Reflect.construct(ClasseUne, []);// Affiche dans la console :// ClasseUne exécutée// new.target vaut ClasseUneconsole.log(obj1 instanceof ClasseUne); // trueconst obj2 = Reflect.construct(ClasseUne, [], AutreClasse);// Affiche dans la console :// ClasseUne exécutée// new.target vaut AutreClasseconsole.log(obj2 instanceof AutreClasse); // trueconsole.log(obj2 instanceof ClasseUne); // falseIl n'y a pas de garantie forte quant à la chaîne de prototypes de l'objet construit, car celle-ci dépend de l'implémentation du constructeur. Par exemple, si le constructeurcible renvoie un objet, c'est cet objet qui sera l'objet construit, quelle que soit la valeur denouvelleCible. Sicible est un proxy avec une trappe pourconstruct, ce sera la trappe qui contrôlera complètement le processus de construction.
function ClasseUne() { return { name: "un" };}function AutreClasse() { return { name: "autre" };}const obj1 = Reflect.construct(ClasseUne, [], AutreClasse);console.log(obj1.name); // 'un'console.log(obj1 instanceof ClasseUne); // falseconsole.log(obj1 instanceof AutreClasse); // falsePour être tout à fait valide,new.target devrait être une fonction constructrice avec une propriétéprototype, mais cette règle n'est pas imposée. Si la valeur de la propriétéprototype n'est pas un objet, l'objet initialisé héritera deObject.prototype.
function ClasseUne() { console.log("ClasseUne exécutée"); console.log(`new.target vaut ${new.target.name}`);}function AutreClasse() { console.log("AutreClasse exécutée"); console.log(`new.target vaut ${new.target.name}`);}AutreClasse.prototype = null;const obj = Reflect.construct(ClasseUne, [], AutreClasse);// Affiche dans la console :// ClasseUne exécutée// new.target vaut AutreClasseconsole.log(Object.getPrototypeOf(obj) === Object.prototype); // trueUne comparaison entreReflect.construct() etObject.create()
Avant l'apparition deReflect, on pouvait construire des objets avec une combinaison donnée de consttructeur et de prototype grâce àObject.create().
function MaClasseA() { this.name = "A";}function MaClasseB() { this.name = "B";}const args = [];const obj1 = Reflect.construct(MaClasseA, args, MaClasseB);const obj2 = Object.create(MaClasseB.prototype);MaClasseA.apply(obj2, args);console.log(obj1.name); // 'A'console.log(obj2.name); // 'A'console.log(obj1 instanceof MaClasseA); // falseconsole.log(obj2 instanceof MaClasseA); // falseconsole.log(obj1 instanceof MaClasseB); // trueconsole.log(obj2 instanceof MaClasseB); // trueToutefois, si les résultats sont identiques, il y a une différence notable. Lorsqu'on utiliseObject.create() etFunction.prototype.apply(), l'opérateurnew.target pointe versundefined dans la fonction utilisée comme constructeur, car le mot-clénew n'est pas utilisé à la création de l'objet (dans cette situation, c'est la même sémantique queapply() qui s'applique, pas celle deconstruct(), même si les fonctions normales se comportent presque identiquement).
En revanche, quand on appelleReflect.construct(),new.target pointe vers la valeur fournie parnouvelleCible si elle indiquée ou verscible sinon.
function MaClasseA() { console.log("MaClasseA"); console.log(new.target);}function MaClasseB() { console.log("MaClasseB"); console.log(new.target);}const obj1 = Reflect.construct(MaClasseA, args);// Affiche dans la console :// MaClasseA// function MaClasseA { ... }const obj2 = Reflect.construct(MaClasseA, args, MaClasseB);// Affiche dans la console :// MaClasseA// function MaClasseB { ... }const obj3 = Object.create(MaClasseB.prototype);MaClasseA.apply(obj3, args);// Affiche dans la console :// MaClasseA// undefinedSpécifications
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-reflect.construct> |