node.jsグローバル変数?


208

私はここで尋ねました: node.jsには継承が必要ですか?

変数を省略して、変数をグローバルスコープに設定できると言われました。

これは私にはうまくいきません。

つまり:

_ = require('underscore');

必要なファイルで_を使用可能にしません。Expressで設定しapp.setて、他の場所で利用できるようにすることもできます。

誰かがこれが動作するはずだと確認できますか?ありがとう。


上記の行はどこにありますか?
JanHančič

3
前の質問の答えがうまくいかない場合は、新しい質問を開始しないでください。むしろそこにコメントを追加し、受け入れられたタグを削除します。
エイリアンハード

5
編集するだけで、現在アクティブな質問リストに表示されます。
MAK、2011年

3
を使用しexportsます。それははるかに優れています。
Emmerman、2011年

1
"use strict"があるため、機能しない可能性があります。ファイルの上部。それは私にとってはそのように機能します。
Geza Turi 2016年

回答:


237

次のglobalように使用できます:

global._ = require('underscore')

28
もう少し情報を提供していただけませんか?これはJavaScriptの一部ですか、それともノードの一部ですか?従うのは良いパターンですか?これを行うべきですか、エクスプレスセットを使用する必要がありますか?ありがとう
ハリー

4
以前のコメントは正しくありません。ブラウザでwindowは、はグローバルオブジェクトです。documentのプロパティですwindow
G-Wiz

77
これは従うべき良いパターンではありません。これを行わないでください。モジュールを分離するために 'require'を使用する規則はよく考えられています。とんでもない理由がなければ、違反するべきではありません。以下の私の応答を参照してください。
Dave Dopson、2012

グローバルは一般的に避けられるべきですが、本当に使いたいのであれば。以下の3つのステートメントはすべて同等であり、varをグローバルスコープに割り当てます。GLOBAL._ = require( 'underscore'); global._ = require( 'underscore'); _ = require( 'underscore');
metaColin

プロジェクトが少し大きくなると、これは維持するのが悪夢になります。私のアプローチをご覧ください。
Oliver Dixon、

219

ノードでは、「グローバル」または「グローバル」オブジェクトを介してグローバル変数を設定できます。

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

またはもっと便利に...

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

ノードのソースから、これらが互いにエイリアスされていることがわかります。

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

上記のコードでは、「this」はグローバルコンテキストです。commonJSモジュールシステム(どのノードが使用するか)では、モジュール内の「this」オブジェクト(つまり「your code」)はグローバルコンテキストではありません。これの証明については、以下を参照して、「this」オブジェクトを生成し、次に巨大な「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: {} }
*/

**注: "GLOBAL._"の設定に関しては、一般的には行う必要がありますvar _ = require('underscore');。はい、Javaで行うように、アンダースコアを使用するすべての単一ファイルでそれを行いますimport com.foo.bar;。これにより、ファイル間のリンケージが「明示的」であるため、コードが何をしているかを理解しやすくなります。少し煩わしいですが、良いことです。....それが説教です。

すべてのルールに例外があります。「GLOBAL._」を設定する必要のあるインスタンスが1つだけありました。私は基本的にJSONである「config」ファイルを定義するためのシステムを作成していましたが、もう少し柔軟性を持たせるために「JSで書かれました」。このような構成ファイルには「require」ステートメントはありませんでしたが、アンダースコアにアクセスできるようにしたいので(システム全体がアンダースコアテンプレートとアンダースコアテンプレートに基づいていました)、「config」を評価する前に「GLOBAL._」を設定しました。つまり、すべてのルールについて、どこかに例外があります。ただし、「require」と入力するのに飽きたので、慣習を破るのではなく、十分な理由がある方がよいでしょう。


7
GLOBALを使用することの欠点は何ですか?なぜ私にはまったく正当な理由が必要なのですか?一番下の行は私のアプリが機能するということですよね?
trusktr 2012

26
最終的には、そうです、あなたが出荷した場合、それだけが重要です。ただし、特定のプラクティスは「ベストプラクティス」として知られており、それらに従うことで、通常、出荷の確率や構築したものを維持できる可能性が高まります。「良い習慣」に従うことの重要性は、プロジェクトの規模とその寿命が長くなるにつれて高まります。私はあらゆる種類の厄介なハックを、一度だけ書き込み、一度も読み取りを行わない(そして「単一の開発者」)の短命なプロジェクトに組み込んだ。より大きなプロジェクトでは、そのようなコーナーカットはプロジェクトの勢いを犠牲にします。
Dave Dopson、2012

48
具体的には、GLOBALの場合、問題は読みやすさの問題です。プログラムが無差別にグローバル変数を使用する場合、それはコードを理解するために、アプリ全体の動的ランタイム状態を理解する必要があることを意味します。これが、プログラマーがグローバルを嫌う理由です。それらを効果的に使用するには数十の方法があると確信していますが、ほとんどの場合、ジュニアプログラマーが製品の悪用に悪用するのを見てきました。
Dave Dopson、2012

2
構成を通常の.jsファイルに入れて、構成をrequireエクスポートする前に呼び出すことができないのはなぜですか?
Azat 2013

4
@Jackie - en.wikipedia.org/wiki/Singleton_pattern。あなたがやっていることがシングルトンパターンにマッピングされているなら、それは理にかなっているかもしれません。DB接続はシングルトンになる可能性があります。1)設定にコストがかかる、2)接続を1回だけ設定する、3)接続オブジェクトが長命であり、ネットワークに障害が発生した場合に失敗状態にならない、 4)接続オブジェクトはスレッドセーフであり、多くの異なる呼び出し元で共有できます。
デイブDopson

78

GLOBALキーワードを使用する他のソリューションは、プロジェクトが大きくなると、保守/可読性(+名前空間の汚染とバグ)の悪夢になります。私はこの間違いを何度も見たことがありますが、修正する手間がかかりました。

JSファイルを使用してから、モジュールのエクスポートを使用します。

例:

globals.js

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

module.exports = Globals;

次に、これらを使用する場合は、requireを使用します。

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

12
私は確かにユニコーンを愛していませんが、あなたのアプローチが好きです。ありがとう。
Jonatas Walker、2015

globals.domainしかし、変更についてはどうですか?
Fizzix、2016年

1
@iLoveUnicorns返信ありがとうございます。ログインしたユーザーのデータを保存するために主に必要なので、 'express-session'などの代替手段を検討します。
Fizzix 2016年

11
私の意見ではこれはより良いアプローチですが、それはグローバルを作成せず、尋ねられた質問に答えません。それは別のアプローチであり、私は常にそれらを奨励しますが、「これはこのスレッドでの唯一の正しい答えです」のような発言の純粋で強気な生意気さは、単にここには属しません。stackoverflow.com/help/be-nice
Thor84no 16

2
これはより良いアプローチかもしれませんが、グローバル名前空間にあるものに依存する外部で作成されたスクリプトを実行しようとしている場合、これは役に立ちません。IOW、これは質問の答えにはなりません。
binki 16

12

のようなグローバル名前空間はどうですか global.MYAPI = {}

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

camilo-martinのコメントの後に編集する:他のすべてのポスターは、関係する悪いパターンについて話します。したがって、その議論はさておき、変数をグローバルに定義する(OPの質問)ための最良の方法は、名前空間を使用することです。

@ヒント:http ://thanpol.as/javascript/development-using-namespaces


3
それrequireが目的です!名前空間を使用することは問題ありませんがglobal.foo = global.foo || {}、すべてのファイルや何かにすべてを適用するのではありません。名前空間を定義するファイルが必要です。子供たちのためにしてください。
Camilo Martin

@ camilo-martinこんにちは、1)global.MYAPI._を定義することで、すべてのファイルで定義する必要がなくなり、それがグローバルである理由です。2)これは子供たちと一緒である必要はありません。それが悪いパターンであるとすべてが言われても、それはプログラマーと彼が言語のこの能力をどのように使用するか与えられた状況に依存します。
Igor Parra 2015

2
はい。ただし、別のファイルで名前空間の機能の一部を宣言するとします。次に、オブジェクトを使用するためにファイルが必要です。これは、逆方向であり、CommonJSおよびCommonSenseにも反します。何かを必要とする場合は、ユーザーコードに名前空間を要求し、名前空間では要求しないようにします。私は何も言わないよ注意に対する理由で人を呼び出して誰の規則がありますだけという、名前空間を。そして、クライアント側では、ノードには何もありません。あなたが言及するリンクは、ノードではなくブラウザに関するものであるため、特定の方法で(グローバルを介して)実行しているリンクを参照してください。
カミロマーティン

1
残念ながら、投稿したURLは、末尾のスラッシュを
省略


5

グローバルを設定するためにグローバル/グローバル名前空間を使用することは悪い習慣であり、理論的にはまったく使用しないことに同意します(理論的には運用上の言葉です)。ただし、(はい、運用)カスタムエラークラスを設定するために使用します。

// Some global/config file that gets called in initialisation

global.MyError = [Function of MyError];

はい、ここではタブーですが、サイト/プロジェクトが場所全体でカスタムエラーを使用している場合、基本的にはどこでも、または少なくともどこかでそれを定義する必要があります。

  1. そもそもErrorクラスを定義する
  2. あなたが投げているスクリプトで
  3. あなたがそれをキャッチしているスクリプトで

グローバル名前空間でカスタムエラーを定義すると、顧客エラーライブラリを要求する手間が省けます。そのカスタムエラーが定義されていないカスタムエラーをスローするイメージング。

また、これが間違っている場合は、最近これを始めたばかりなので、お知らせください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.