Fonction F () {if (! (Cette instance de F)) {return new F ()}; …}

Quelle est l'utilisation de la construction: function F() { if (!(this instanceof F)) { return new F() }; ... } function F() { if (!(this instanceof F)) { return new F() }; ... } ?

J'ai trouvé cela dans un pty.js pour Node. Voici le code original:

 function Terminal(file, args, opt) { if (!(this instanceof Terminal)) { return new Terminal(file, args, opt); } var self = this , env , cwd , name , cols , rows , term; -------------------SKIP----------------------------------- Terminal.total++; this.socket.on('close', function() { Terminal.total--; self._close(); self.emit('exit', null); }); env = null; } 

Cela signifie que si la fonction était appelée sans le new opérateur, elle retournera automatiquement une nouvelle instance.

Par exemple, si vous n'aviez pas cette garantie, et avez-vous …

 var t = Terminal(); 

… alors, this tout en exécutant Terminal() pointerait vers la window (ou votre objet global, fancy non-browser guy / gal), certainement pas ce que vous voulez.

En déterminant que c'est en fait une instance de Terminal , nous pouvons continuer. Sinon, la sauvegarde renvoie un nouvel objet.

Ensuite, nous pouvons simplement utiliser les deux formes …

 var t = Terminal(); // Will be same as `new Terminal()` 

C'est juste pour s'assurer que cela fonctionnera même si F est appelé sans new .

Lorsque vous appelez F avec new , dans cette fonction, this s'agit de la nouvelle instance.

Ensuite, si this n'est pas une instance de F ( !(this instanceof F) ), cela signifie que F n'a pas été appelé à l'aide de new . Dans ce cas, F s'appelle lui-même, maintenant avec new .

En plus des grandes explications de ce fil, il est intéressant de voir ce qui se passe sous le capot. La spécification ECMAScript (où Javascript est basé) définit un objet global . Ceci est implémenté différemment dans différents environnements d'exécution. Dans votre navigateur typique, c'est l'objet window dans Node.js c'est l'objet root . Chaque fonction définie "in the wild" (non attachée à un objet créé par l'utilisateur) deviendra une propriété de l'objet global. Dans Node.js, vous pouvez essayer:

 > function Test() {}; > root.Test [Function: Test] 

Maintenant, this variable indique l'objet dans lequel la fonction est membre . Donc, dans l'exemple ci-dessus:

 > function Test() { ... console.log(this === root); ... }; > Test() true 

Même chose pour votre Terminal fonction. Si vous l'exécutez, this indiquera l'objet global qui n'est évidemment pas une instance de Terminal !

Lorsque vous appelez une fonction à l'aide du new opérateur, un objet est renvoyé qui aura accès à une propriété appelée constructor qui rappellera cette fonction. C'est quelque chose qui équivaut à:

 > var instance = {}; > instance.constructor = Terminal; > instance.constructor(); 

Donc, lorsque le conditionnel échoue et que la fonction Terminal fonctionne à travers la new Terminal() , this indiquera une instance nouvellement créée qui est de type Terminal!

Si vous souhaitez obtenir plus d'informations techniques, l' instance n'a pas de propriété constructor elle-même. Il est plutôt lié (via la chaîne prototype *), à un objet privé ** (créé par l'exécution) qui possède une propriété constructor indiquant la fonction Terminal. Cet objet privé est rappelé par la fonction à travers un prototype propriété. D.Crockford présente ceci en pseudocode comme suit:

 Terminal.prototype = {constructor: Terminal}; 

Encore une fois, ce n'est que lorsque vous appelez la fonction avec une new .

* Si une propriété n'est pas trouvée, l'objet recherchera l'objet désigné par la propriété __proto__ .

** (imaginez quelque chose comme un objet appelé _Terminal que vous ne pouvez pas accéder par nom)