217 votes

Variables globales Node.js

J'ai posé la question ici : Node.js nécessite-t-il l'héritage ?

On m'a dit que je pouvais placer des variables dans le champ d'application global en omettant la variable.

Cela ne fonctionne pas pour moi.

En d'autres termes, ce qui suit ne fait pas de la _ disponibles dans les fichiers requis.

_ = require('underscore');

Je peux paramétrer avec Express.js la fonction app.set et qu'il soit disponible ailleurs.

Est-ce ainsi que cela est censé fonctionner ?

0 votes

Où se trouve la ligne ci-dessus ?

3 votes

Je pense que vous ne devriez pas poser une nouvelle question si la réponse à votre question précédente ne fonctionne pas. Ajoutez plutôt un commentaire à cet endroit et supprimez l'étiquette "accepté".

0 votes

@alienhard mais c'est vieux, personne ne va le voir.

242voto

masylum Points 4819

Vous pouvez utiliser global comme suit :

global._ = require('underscore')

28 votes

Pourriez-vous nous fournir un peu plus d'informations ? Cela fait-il partie de javascript ou de node ? Est-ce un bon modèle à suivre ? Je ne sais pas si je dois le faire ou si je dois utiliser express set. Merci de votre compréhension.

4 votes

Le commentaire précédent est incorrect. Dans le navigateur, window est l'objet global. document est une propriété de window .

78 votes

Ce n'est PAS un bon modèle à suivre. Ne faites pas cela. La convention qui consiste à utiliser "require" pour découpler les modules est bien pensée. Vous ne devriez pas l'enfreindre sans une très bonne raison. Voir ma réponse ci-dessous.

221voto

Dave Dopson Points 16690

Dans Node.js, vous pouvez définir des variables globales via l'objet "global" ou "GLOBAL" :

GLOBAL._ = require('underscore'); // But you "shouldn't" do this! (see note below)

ou plus utilement...

GLOBAL.window = GLOBAL;  // Like in the browser

Dans le code source de Node.js, vous pouvez voir que ces éléments sont liés l'un à l'autre :

node-v0.6.6/src/node.js:
28:     global = this;
128:    global.GLOBAL = global;

Dans le code ci-dessus, "this" est le contexte global. Avec le contexte CommonJS (que Node.js utilise), l'objet "this" à l'intérieur d'un module (c'est-à-dire "votre code") est no le contexte mondial. Pour s'en convaincre, voir ci-dessous où je crache l'objet "this" puis l'objet géant "GLOBAL".

console.log("\nTHIS:");
console.log(this);
console.log("\nGLOBAL:");
console.log(global);

/* Outputs ...

THIS:
{}

GLOBAL:
{ ArrayBuffer: [Function: ArrayBuffer],
  Int8Array: { [Function] BYTES_PER_ELEMENT: 1 },
  Uint8Array: { [Function] BYTES_PER_ELEMENT: 1 },
  Int16Array: { [Function] BYTES_PER_ELEMENT: 2 },
  Uint16Array: { [Function] BYTES_PER_ELEMENT: 2 },
  Int32Array: { [Function] BYTES_PER_ELEMENT: 4 },
  Uint32Array: { [Function] BYTES_PER_ELEMENT: 4 },
  Float32Array: { [Function] BYTES_PER_ELEMENT: 4 },
  Float64Array: { [Function] BYTES_PER_ELEMENT: 8 },
  DataView: [Function: DataView],
  global: [Circular],
  process:
   { EventEmitter: [Function: EventEmitter],
     title: 'node',
     assert: [Function],
     version: 'v0.6.5',
     _tickCallback: [Function],
     moduleLoadList:
      [ 'Binding evals',
        'Binding natives',
        'NativeModule events',
        'NativeModule buffer',
        'Binding buffer',
        'NativeModule assert',
        'NativeModule util',
        'NativeModule path',
        'NativeModule module',
        'NativeModule fs',
        'Binding fs',
        'Binding constants',
        'NativeModule stream',
        'NativeModule console',
        'Binding tty_wrap',
        'NativeModule tty',
        'NativeModule net',
        'NativeModule timers',
        'Binding timer_wrap',
        'NativeModule _linklist' ],
     versions:
      { node: '0.6.5',
        v8: '3.6.6.11',
        ares: '1.7.5-DEV',
        uv: '0.6',
        openssl: '0.9.8n' },
     nextTick: [Function],
     stdout: [Getter],
     arch: 'x64',
     stderr: [Getter],
     platform: 'darwin',
     argv: [ 'node', '/workspace/zd/zgap/darwin-js/index.js' ],
     stdin: [Getter],
     env:
      { TERM_PROGRAM: 'iTerm.app',
        'COM_GOOGLE_CHROME_FRAMEWORK_SERVICE_PROCESS/USERS/DDOPSON/LIBRARY/APPLICATION_SUPPORT/GOOGLE/CHROME_SOCKET': '/tmp/launch-nNl1vo/ServiceProcessSocket',
        TERM: 'xterm',
        SHELL: '/bin/bash',
        TMPDIR: '/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/',
        Apple_PubSub_Socket_Render: '/tmp/launch-9Ga0PT/Render',
        USER: 'ddopson',
        COMMAND_MODE: 'unix2003',
        SSH_AUTH_SOCK: '/tmp/launch-sD905b/Listeners',
        __CF_USER_TEXT_ENCODING: '0x12D732E7:0:0',
        PATH: '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/bin:/usr/X11/bin',
        PWD: '/workspace/zd/zgap/darwin-js',
        LANG: 'en_US.UTF-8',
        ITERM_PROFILE: 'Default',
        SHLVL: '1',
        COLORFGBG: '7;0',
        HOME: '/Users/ddopson',
        ITERM_SESSION_ID: 'w0t0p0',
        LOGNAME: 'ddopson',
        DISPLAY: '/tmp/launch-l9RQXI/org.x:0',
        OLDPWD: '/workspace/zd/zgap/darwin-js/external',
        _: './index.js' },
     openStdin: [Function],
     exit: [Function],
     pid: 10321,
     features:
      { debug: false,
        uv: true,
        ipv6: true,
        tls_npn: false,
        tls_sni: true,
        tls: true },
     kill: [Function],
     execPath: '/usr/local/bin/node',
     addListener: [Function],
     _needTickCallback: [Function],
     on: [Function],
     removeListener: [Function],
     reallyExit: [Function],
     chdir: [Function],
     debug: [Function],
     error: [Function],
     cwd: [Function],
     watchFile: [Function],
     umask: [Function],
     getuid: [Function],
     unwatchFile: [Function],
     mixin: [Function],
     setuid: [Function],
     setgid: [Function],
     createChildProcess: [Function],
     getgid: [Function],
     inherits: [Function],
     _kill: [Function],
     _byteLength: [Function],
     mainModule:
      { id: '.',
        exports: {},
        parent: null,
        filename: '/workspace/zd/zgap/darwin-js/index.js',
        loaded: false,
        exited: false,
        children: [],
        paths: [Object] },
     _debugProcess: [Function],
     dlopen: [Function],
     uptime: [Function],
     memoryUsage: [Function],
     uvCounters: [Function],
     binding: [Function] },
  GLOBAL: [Circular],
  root: [Circular],
  Buffer:
   { [Function: Buffer]
     poolSize: 8192,
     isBuffer: [Function: isBuffer],
     byteLength: [Function],
     _charsWritten: 8 },
  setTimeout: [Function],
  setInterval: [Function],
  clearTimeout: [Function],
  clearInterval: [Function],
  console: [Getter],
  window: [Circular],
  navigator: {} }
*/

** Note : en ce qui concerne le réglage de "GLOBAL._", en général vous devriez simplement faire var _ = require('underscore'); . Oui, vous faites cela dans chaque fichier qui utilise Underscore.js, tout comme en Java vous faites import com.foo.bar; . Il est ainsi plus facile de comprendre ce que fait votre code, car les liens entre les fichiers sont "explicites". C'est légèrement ennuyeux, mais c'est une bonne chose. .... C'est la prédication.

Il y a une exception à chaque règle. J'ai eu exactement exactement un où je devais définir "GLOBAL._". Je créais un système pour définir des fichiers de "configuration" qui étaient essentiellement JSON, mais qui étaient "écrits en JavaScript" pour permettre un peu plus de flexibilité. Ces fichiers de configuration n'avaient pas d'instructions "require", mais je voulais qu'ils aient accès à Underscore.js (le fichier entière était basé sur Underscore.js et les templates Underscore.js), donc avant d'évaluer la "configuration", je mettais "GLOBAL._". Donc oui, pour chaque règle, il y a une exception quelque part. Mais vous avez intérêt à avoir une sacrée bonne raison et pas seulement "j'en ai marre de taper 'require', donc je veux rompre avec la convention".

7 votes

Quels sont les inconvénients de l'utilisation de GLOBAL ? Pourquoi ai-je besoin d'une bonne raison ? L'essentiel est que mon application fonctionne, n'est-ce pas ?

26 votes

En fin de compte, oui, si vous expédiez, c'est tout ce qui compte. Cependant, certaines pratiques sont connues sous le nom de "meilleures pratiques" et leur respect augmente généralement vos chances d'expédier et/ou d'être en mesure de maintenir ce que vous avez construit. L'importance du respect des "bonnes pratiques" augmente avec la taille du projet et sa longévité. J'ai construit toutes sortes de hacks désagréables dans des projets de courte durée qui étaient écrits une seule fois, lus jamais (et "mono-développeur"). Dans un projet plus important, ce genre de coupes sombres finit par vous coûter l'élan du projet.

48 votes

En ce qui concerne GLOBAL, il s'agit plus particulièrement d'un problème de lisibilité. Si votre programme utilise des variables globales de manière inconsidérée, cela signifie que pour comprendre le code, je dois comprendre l'état dynamique de l'application dans son ensemble. C'est pourquoi les programmeurs se méfient des variables globales. Je suis sûr qu'il existe des dizaines de façons de les utiliser efficacement, mais nous avons surtout vu des programmeurs débutants en abuser au détriment du produit.

81voto

iLoveUnicorns Points 195

Les autres solutions qui utilisent le mot-clé GLOBAL sont un cauchemar pour la maintenance et la lisibilité (+pollution des espaces de noms et bogues) lorsque le projet devient plus important. J'ai vu cette erreur à plusieurs reprises et j'ai dû la corriger.

Utiliser un fichier JavaScript et ensuite utiliser les exportations de modules.

Ejemplo:

Fichier globals.js

var Globals = {
    'domain':'www.MrGlobal.com';
}

module.exports = Globals;

Ensuite, si vous voulez les utiliser, utilisez exiger .

var globals = require('globals'); // << globals.js path
globals.domain // << Domain.

13voto

Igor Parra Points 3858

Utilisez un espace de noms global comme global.MYAPI = {} :

global.MYAPI._ = require('underscore')

Toutes les autres affiches parlent du mauvais modèle impliqué. Donc, en laissant cette discussion de côté, la meilleure façon d'avoir une variable définie globalement (la question de l'OP) est à travers les espaces de noms.

Conseil : Développement à l'aide d'espaces de noms

3 votes

C'est ce que require est pour ! Il est possible d'utiliser des espaces de noms, mais il ne faut pas faire n'importe quoi. global.foo = global.foo || {} sur tous les fichiers, ou quelque chose comme ça. Exiger le fichier qui définit l'espace de noms. Le faire pour les enfants.

0 votes

@camilo-martin Bonjour, 1) En définissant global.MYAPI._ vous n'avez pas besoin de le définir dans tous les fichiers, c'est la raison pour laquelle il est global. 2) Cela n'a rien à voir avec les enfants. Même si tout le monde dit que c'est un mauvais modèle, cela dépend du programmeur et de la situation donnée, comment il utilise cette capacité du langage.

2 votes

Oui, mais imaginons que vous déclariez certaines des fonctionnalités d'un espace de noms dans un fichier séparé. Vous avez alors besoin d'un fichier pour utiliser l'objet, ce qui est rétrograde et va à l'encontre de CommonJS et de CommonSense. Si vous voulez exiger des choses, faites en sorte que le code utilisateur exige l'espace de noms et ne soit pas exigé par l'espace de noms. Notez que je ne dis rien contre Il y a des conventions sur qui appelle qui pour une raison précise. Et côté client, vous n'avez pas ce que node a ; voir le lien que vous mentionnez fait les choses d'une certaine manière (à travers global) parce qu'il s'agit du navigateur et non de node.

11voto

Joao Falcao Points 274

Vous pouvez simplement utiliser l'objet global.

var X = ['a', 'b', 'c'];
global.x = X;

console.log(x);
//['a', 'b', 'c']

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X