Usare ‘return’ quando si creano oggetti con ‘new’

Oggi ho trovato qualcosa di molto strano: se crei oggetti con una funzione di costruzione e la new parola chiave, ma return una funzione dal costruttore, si comporta in questo modo:

  1. L'”object” appena creato è invece una funzione.
  2. Quella nuova funzione può essere invocata come normale, tuttavia …
  3. Se mantieni un riferimento a this nella funzione di costruzione, this riferimento a un object che è stato creato correttamente dal costruttore. È quello che ti aspettavi di essere restituito da new .

Ecco un esempio:

 function Constructor() { var self = this; this.name = 'instance'; return function() { return self; } } 

Quindi, se l’hai istanziato in questo modo: var instance = new Constructor() Il seguente risultato:

 typeof instance //returns "function" typeof instance() //returns "object" instance() //returns { name: 'instance' } 

Quindi immagino di avere tre domande:

  1. È legale e funziona cross-browser? È davvero fantastico e penso che possa essere usato in molti modi, ma questo comportamento è affidabile?
  2. Cosa succede in background che causa questo comportamento?
  3. (forse ha risposto con 2, ma …) Il nuovo object (quello a cui si fa riferimento con ‘this’) all’interno della nuova istanza, in modo che sia tutto autocontenuto e corretto dal garbage collector?

  1. Sì, mentre un costruttore di default restituisce il nuovo object in costruzione (a cui fa riferimento this ) , è ansible sovrascrivere quel valore restituito finché si restituisce un object . Poiché una funzione è un object, puoi restituirla come nel tuo esempio. L’object appena creato non è una funzione stessa, ma la funzione restituita fa riferimento all’object appena creato nel suo ambito variabile.

  2. Vedi # 1

  3. Questo perché una funzione crea una chiusura, quindi continua a fare riferimento alla variabile self , che fa riferimento all’object reale che si sta costruendo. Quindi non direi che è “dentro” qualsiasi cosa, ma piuttosto è semplicemente parte dell’ambito variabile della funzione.

La cosa da capire è che la tua funzione non è diversa da qualsiasi altra funzione. Proprio come se avessi invece restituito una matrice, avresti semplicemente una matrice regolare, che potrebbe fare riferimento al nuovo object.

 function Constructor() { this.name = 'instance'; return [ this ]; // Instead return an Array that references the new object } 

Bene, questa è una domanda davvero buona e, come avrete intuito, non ha risposto facilmente.

Per dirla molto semplicemente:
1) Sì e Sì; questa è una delle straordinarie funzionalità che non si trovano nei linguaggi di programmazione “tradizionali”.
2) si prega di leggere su chiusure (link sotto)
3) Sì (per favore leggi di più)

Si dovrebbe leggere di più su Javascript Closures: http://jibbering.com/faq/notes/closures/
http://www.javascriptkit.com/javatutors/closures.shtml (qui hai alcuni buoni esempi di lavoro)

e, più in particolare, il modello di eredità parassitaria:
http://blog.higher-order.net/2008/02/21/javascript-parasitic-inheritance-power-constructors-and-instanceof/

spero che questo possa essere d’aiuto

questo è ciò che chiami chiusura

ciò che fa è creare un ambiente di codice autonomo (comunemente noto come object)

 typeof instance //returns "function" - since it's not "fired" or called. just returns the function declaration (correct me if i'm wrong) typeof instance() //returns "object" - it returns an object since you called it instance() //returns an object also - you called it, but you didn't store it 

un esempio di un object costruito usando una chiusura:

 function Constructor() { var privateProperty = 'private'; var privateMethod = function(){ alert('called from public method'); }; //return only what's to be seen in public return { publicProperty: 'im public', publicMethod: function(){ alert('called from public method'); } getter: privateMethod //assign to call the private method } } var myObj = Constructor(); var pubProp = myObj.publicProperty; // pubProp = 'im public' myObj.publicMethod() //alert: 'called from public method'; myObj.getter() //alert: 'called from public method'; //cannot access since "private": myObj.privateProperty myObj.privateMethod