2013-03-08 7 views
5

In qualsiasi browser Web in cui viene eseguito il seguente script, verrà inviato 'wee' alla console. Nel nodo invia {}.Dove vengono memorizzati i vars in Nodejs?

var d = 'wee'; 
console.log(this.d); 

mi rendo conto che nel Nodo this si riferisce alle esportazioni oggetto in questo caso. So della variabile global e non è quello che sto cercando di accedere. Inoltre, lo script sopra non imposta d sull'oggetto globale. Dove diavolo va? Posso accedervi esplicitamente con lo console.log(d); nello script sopra, ma sembra essere nascosto in uno spazio non standard senza una buona ragione.

mi rendo anche conto che la rimozione var dichiarerà d sull'oggetto global, che è il comportamento previsto anche se sembra stupido avere var a portata livello superiore memorizzare i valori in un luogo diverso da variabili "nude". Voglio dire, non è il punto in cui il sistema del modulo dovrebbe essere una sorta di profilassi digitale per proteggersi dall'inquinamento globale? Qui sembra così facile rompere il modello e così difficile da fare qualcosa di standard.

d non è dichiarato sull'oggetto module.

Non devo giustificare il motivo per cui sto facendo questa domanda, ma risponderò al primo troll di venire con un "ma perché vuoi fare taht hurr durrrr".

var d = {}; 
d.bleep = 'y'; 
var a = Object.keys(d); 

d.bloop = 'y'; 
d.blop = 'y'; 

var b = Object.keys(d); 

// c = b - a; 
var c = b.filter(function (item) { 
    if(a.indexOf(item) === -1) { 
     return true; 
    } 
    return false; 
}); 

console.log(a,b,c); 

Nello stesso modo che posso distinguere fra alcuni stati oggetto di d, dovrei essere in grado di differenziare gli stati di portata livello superiore. In un browser questo è l'oggetto window, a cui si fa riferimento da this nell'ambito di livello superiore. Dovrei essere in grado di valutare le proprietà dell'ambiente prima e dopo l'esecuzione dello script per determinare un gran numero di cose, una delle quali sarebbe l'ispezione di funzioni e variabili dichiarate nello scope top di uno script arbitrario che potrebbero quindi essere applicate al esporta oggetto. Ciò renderebbe più facile generare programatically wrapper di moduli per gli script che non sono stati scritti come moduli con un semplice forEach applicata alla lista delle funzioni di alto livello e le variabili da assegnare whateverThisIs['varFunc'] a module.exports['varFunc'] ...

e roba del genere ...

Questo comportamento sembra essere quello di una funzione anonima. In una funzione anonima this potrebbe fare riferimento all'oggetto window, var s dovrebbe essere chiamato direttamente (come sono nel campo di visibilità di anon) e, le variabili rilasciate dichiarate senza la parola chiave var potrebbero finire nell'oggetto window. Non ho ancora letto l'intero manuale, forse è esattamente quello che sta succedendo, ma avevo l'impressione che ogni modulo fosse eseguito nel proprio contesto (finestra) e che il nodo passasse messaggi tra i contesti dei moduli attraverso l'uso di global e module.exports ...

Non so. Voglio sapere però. Se lo sai, fammi sapere.

+2

va nella portata variabile locale. In un modulo, il codice è racchiuso in una funzione. Non lo vedi, –

+0

Quindi è solo una funzione anonima allora? Di sicuro? – Kastor

+2

Sì ... beh, non ricordo se è anonimo, ma non importa. È una funzione Il primo parametro definito per la funzione è 'exports' e un oggetto vuoto viene passato a quel parametro. Lo stesso oggetto è impostato come valore 'this' della funzione. Puoi testarlo con 'console.log (argomenti [0] === exports, argomenti [0] === this);', e otterrai 'true' per entrambi. –

risposta

10

Così ogni modulo nodo è avvolto come il corpo di una funzione come shown here in the node source code

NativeModule.wrapper = [ 
    '(function (exports, require, module, __filename, __dirname) { ', 
    '\n});' 
]; 

Quindi, se si dichiara una variabile con var, è la funzione locale al modulo, fondamentalmente una variabile privata per quel modulo . Non è una proprietà di global, module, module.exports o this. Se si dimentica lo var, esso entra nell'oggetto global come una proprietà. Se si crea in modo esplicito una proprietà su this, questo va in exports ed è disponibile per altri moduli.

Ecco un piccolo programma che si spera illuminante.

var aDeclaredVar = '*aDeclaredVar*'; 
undeclaredVar = '*undeclaredVar*'; 
this.aThisProperty = '*aThisProperty*'; 
module.aModuleProperty = '*aModuleProperty*'; 
module.exports.anExportProperty = '*anExportProperty*'; 

console.log('this', this); 
console.log('this === exports', this === exports); 
console.log('this === module', this === module); 
console.log('this === module.exports', this === module.exports); 
console.log('aDeclaredVar', aDeclaredVar); 
console.log('undeclaredVar', undeclaredVar); 
console.log('this.aThisProperty', this.aThisProperty); 
console.log('module.aModuleProperty', module.aModuleProperty); 
console.log('module.exports.anExportProperty', module.exports.anExportProperty); 
console.log('global.undeclaredVar', global.undeclaredVar); 
console.log('global.aDeclaredVar', global.aDeclaredVar); 

Ed è uscita:

this { aThisProperty: '*aThisProperty*', 
    anExportProperty: '*anExportProperty*' } 
this === exports true 
this === module false 
this === module.exports true 
aDeclaredVar *aDeclaredVar* 
undeclaredVar *undeclaredVar* 
this.aThisProperty *aThisProperty* 
module.aModuleProperty *aModuleProperty* 
module.exports.anExportProperty *anExportProperty* 
global.undeclaredVar *undeclaredVar* 
global.aDeclaredVar undefined 
+0

Grazie per il link alla fonte. : D Non ho mai provato a introspettare le vars locali di una funzione prima. Non so se c'è un trucco da fare o meno, ma di sicuro il comportamento che vedo ha senso ora che conosco il contesto. È come scrivere bookmarklets. – Kastor

+0

così ho provato a eseguire uno script che avrebbe terminato il wrapper ...}; Troverò qualcos'altro da fare : D – Kastor

+0

Grazie per aver risolto tutto ... stava scrivendo un'estensione nativa del nodo e stavo lottando con questo per un paio di giorni! +1 – jkp