variabel global node.js?

208

Saya bertanya di sini: node.js memerlukan warisan?

dan diberitahu bahwa saya dapat mengatur variabel ke ruang lingkup global dengan meninggalkan var.

Ini tidak bekerja untuk saya.

yaitu:

_ = require('underscore');

Tidak membuat _ tersedia pada file yang diperlukan. Saya dapat mengatur dengan express app.setdan memilikinya tersedia di tempat lain.

Adakah yang bisa mengkonfirmasi bahwa ini seharusnya berhasil? Terima kasih.

Harry
sumber
Di mana Anda memiliki garis di atas?
Jan Hančič
3
Saya pikir Anda tidak harus memulai pertanyaan baru jika jawaban untuk pertanyaan Anda sebelumnya tidak berfungsi. Sebaliknya tambahkan komentar di sana dan hapus tag yang diterima.
alienhard
5
Hanya mengeditnya membuatnya muncul dalam daftar pertanyaan yang sedang aktif.
MAK
3
Gunakan exports. Jauh lebih baik.
Emmerman
1
Mungkin itu tidak berhasil karena Anda telah "menggunakan ketat"; di bagian atas file Anda. Ini berfungsi seperti itu untuk saya.
Geza Turi

Jawaban:

237

Anda dapat menggunakan globalseperti ini:

global._ = require('underscore')
masylum
sumber
28
Bisakah Anda memberikan sedikit informasi lebih lanjut? Apakah ini bagian dari javascript atau bagian dari simpul? Apakah ini pola yang baik untuk diikuti? Seperti apakah saya harus melakukan ini atau saya harus menggunakan set ekspres? Terima kasih
Harry
4
Komentar sebelumnya salah. Di browser, windowadalah objek global. documentadalah properti dari window.
G-Wiz
77
Ini BUKAN pola yang baik untuk diikuti. Jangan lakukan ini. Konvensi menggunakan 'keharusan' untuk memisahkan modul sudah dipikirkan dengan baik. Anda seharusnya tidak melanggarnya tanpa alasan kuat. Lihat tanggapan saya di bawah ini.
Dave Dopson
Global umumnya harus dihindari, tetapi jika Anda benar-benar ingin menggunakannya. 3 pernyataan di bawah ini semuanya setara dan akan menetapkan var ke lingkup global: GLOBAL._ = wajib ('garis bawah'); global._ = wajibkan ('garis bawah'); _ = wajib ('garis bawah');
metaColin
Ketika proyek Anda mulai menjadi sedikit lebih besar, ini akan menjadi mimpi buruk untuk dipertahankan. Silakan lihat pendekatan saya.
Oliver Dixon
219

Dalam node, Anda dapat mengatur variabel global melalui objek "global" atau "GLOBAL":

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

atau lebih bermanfaat ...

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

Dari sumber simpul, Anda dapat melihat bahwa ini saling terkait:

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

Dalam kode di atas, "ini" adalah konteks global. Dengan sistem modul commonJS (yang menggunakan simpul), objek "ini" di dalam modul (yaitu, "kode Anda") BUKAN konteks global. Untuk buktinya, lihat di bawah ini di mana saya memuntahkan objek "ini" dan kemudian objek "GLOBAL" raksasa.

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: {} }
*/

** Catatan: tentang pengaturan "GLOBAL._", secara umum Anda hanya perlu melakukannya var _ = require('underscore');. Ya, Anda melakukannya di setiap file yang menggunakan garis bawah, seperti halnya di Java yang Anda lakukanimport com.foo.bar; . Ini membuatnya lebih mudah untuk mengetahui apa yang kode Anda lakukan karena hubungan antar file bersifat 'eksplisit'. Agak menyebalkan, tapi bagus. .... Itulah khotbahnya.

Ada pengecualian untuk setiap aturan. Saya memiliki persis satu contoh di mana saya perlu mengatur "GLOBAL._". Saya sedang membuat sistem untuk mendefinisikan "config" file yang pada dasarnya JSON, tetapi "ditulis dalam JS" untuk memungkinkan fleksibilitas yang sedikit lebih. File konfigurasi seperti itu tidak memiliki pernyataan 'wajib', tapi saya ingin mereka memiliki akses ke garis bawah (sistem SELURUH didasarkan pada template garis bawah dan garis bawah), jadi sebelum mengevaluasi "konfigurasi", saya akan menetapkan "GLOBAL._". Jadi ya, untuk setiap aturan, ada pengecualian di suatu tempat. Tetapi Anda sebaiknya memiliki alasan yang sangat bagus dan bukan hanya "saya bosan mengetik 'wajib' jadi saya ingin istirahat dengan konvensi".

Dave Dopson
sumber
7
Apa kerugian menggunakan GLOBAL? Mengapa saya perlu alasan yang sangat bagus? Intinya adalah aplikasi saya berfungsi, bukan?
trusktr
26
akhirnya, ya, jika Anda mengirim, itu yang terpenting. Namun, praktik tertentu dikenal sebagai "praktik terbaik" dan mengikutinya biasanya meningkatkan peluang pengiriman dan / atau mempertahankan apa yang telah Anda bangun. Pentingnya mengikuti "praktik yang baik" meningkat dengan ukuran proyek dan umur panjangnya. Saya telah membangun semua jenis peretasan jahat ke dalam proyek-proyek berumur pendek yang bersifat menulis-sekali, tidak pernah dibaca (dan "pengembang tunggal"). Dalam sebuah proyek yang lebih besar, pemotongan sudut semacam itu akhirnya membuat Anda kehilangan momentum proyek.
Dave Dopson
48
Secara khusus, dengan GLOBAL, masalah ini adalah keterbacaan. Jika program Anda secara sembarangan menggunakan variabel global, itu berarti bahwa untuk memahami kode, saya harus memahami keadaan runtime dinamis dari seluruh aplikasi. Inilah sebabnya mengapa programmer curiga terhadap global. Saya yakin ada lusinan cara untuk menggunakannya secara efektif, tetapi kami sebagian besar baru saja melihatnya dilecehkan oleh para programmer junior karena sakitnya produk tersebut.
Dave Dopson
2
Mengapa Anda tidak bisa memasukkan konfigurasi saja ke dalam .jsfile dan panggilan biasa requiresebelum mengekspor konfigurasi?
Azat
4
@Jackie - en.wikipedia.org/wiki/Singleton_pattern . jika apa yang Anda lakukan peta dengan pola Singleton, maka mungkin masuk akal. Koneksi DB dapat berupa lajang ketika: 1) pengaturan mahal, 2) Anda hanya ingin koneksi diatur sekali, 3) objek koneksi berumur panjang dan tidak akan memasuki kondisi gagal jika terjadi cegukan jaringan, 4) objek koneksi aman-thread / dapat dibagi oleh banyak penelepon yang berbeda.
Dave Dopson
78

Solusi lain yang menggunakan kata kunci GLOBAL adalah mimpi buruk untuk mempertahankan / keterbacaan (+ namespace polusi dan bug) ketika proyek semakin besar. Saya telah melihat kesalahan ini berkali-kali dan memiliki kesulitan untuk memperbaikinya.

Gunakan file JS kemudian gunakan ekspor modul.

Contoh:

globals.js

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

module.exports = Globals;

Maka jika Anda ingin menggunakan ini, gunakan wajib.

var globals = require('globals'); //<< globals.js path
globals.domain //<< Domain.
Oliver Dixon
sumber
13
Saya pasti tidak suka Unicorn tetapi suka pendekatan Anda. Terima kasih.
Jonatas Walker
Bagaimana dengan perubahan globals.domain?
Fizzix
1
@ iLoveUnicorns terima kasih telah membalas. Saya akan mencari alternatif seperti 'sesi ekspres' karena saya terutama membutuhkannya untuk menyimpan data pengguna yang masuk.
Fizzix
11
Meskipun menurut saya ini adalah pendekatan yang lebih baik, ini tidak menciptakan global dan tidak menjawab pertanyaan yang diajukan. Ini adalah pendekatan alternatif dan saya selalu mendorong itu, namun pernyataan sombong semata-mata seperti "Ini adalah satu-satunya jawaban yang benar pada utas ini" tidak seharusnya ada di sini. stackoverflow.com/help/be-nice
Thor84no
2
Ini mungkin pendekatan yang lebih baik, tetapi jika Anda mencoba menjalankan skrip yang ditulis secara eksternal yang mengandalkan sesuatu yang ada di ruang nama global, ini tidak membantu Anda. TKI, ini tidak menjawab pertanyaan.
binki
12

Bagaimana dengan namespace global global.MYAPI = {}

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

Edit setelah komentar camilo-martin : Semua poster lain berbicara tentang pola buruk yang terlibat. Jadi mengesampingkan diskusi itu, cara terbaik untuk memiliki variabel yang didefinisikan secara global (pertanyaan OP) adalah melalui ruang nama.

@ tip: http://thanpol.as/javascript/development-using-namespaces

Igor Parra
sumber
3
Itu untuk apa require! Tidak apa-apa menggunakan ruang nama, tapi jangan gunakan global.foo = global.foo || {}semua file, atau apa saja. Membutuhkan file yang mendefinisikan namespace. Lakukan untuk anak-anak.
Camilo Martin
@ camilo-martin Hai, 1) Dengan mendefinisikan global.MYAPI._ Anda tidak perlu mendefinisikannya di semua file, Itulah alasannya menjadi global. 2) Ini tidak ada hubungannya dengan anak-anak. Bahkan jika semua mengatakan itu adalah pola yang buruk, itu tergantung pada programmer dan situasi yang diberikan bagaimana dia menggunakan kemampuan bahasa ini.
Igor Parra
2
Ya, tetapi katakanlah Anda mendeklarasikan beberapa fungsi namespace dalam file terpisah. Kemudian Anda memerlukan file untuk menggunakan objek, yang mundur dan bertentangan dengan CommonJS dan CommonSense juga. Jika Anda akan membutuhkan barang, minta kode pengguna meminta namespace dan tidak diperlukan oleh namespace. Catatan Saya tidak mengatakan apa - apa terhadap ruang nama, hanya ada konvensi tentang siapa yang memanggil siapa karena suatu alasan. Dan di sisi klien Anda tidak memiliki simpul apa; lihat tautan yang Anda sebutkan melakukan hal-hal dengan cara tertentu (melalui global) karena ini tentang peramban dan bukan simpul.
Camilo Martin
1
Sayangnya URL yang Anda posting hanya berfungsi jika Anda meninggalkan garis miring;)
Dirigible
10

Anda bisa menggunakan objek global.

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

console.log(x);
//['a', 'b', 'c']
Joao Falcao
sumber
5

Saya setuju bahwa menggunakan namespace global / GLOBAL untuk menetapkan apa pun global adalah praktik buruk dan tidak menggunakannya sama sekali dalam teori ( secara teori menjadi kata yang digunakan). Namun (ya, operatif) saya menggunakannya untuk mengatur kelas kesalahan kustom:

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

global.MyError = [Function of MyError];

Ya, tabu di sini, tetapi jika situs / proyek Anda menggunakan kesalahan khusus di seluruh tempat, pada dasarnya Anda perlu mendefinisikannya di mana-mana, atau setidaknya di suatu tempat untuk:

  1. Tentukan kelas Kesalahan di tempat pertama
  2. Dalam skrip tempat Anda melemparkannya
  3. Dalam skrip tempat Anda menangkapnya

Menentukan kesalahan khusus saya di namespace global menyelamatkan saya dari kerumitan mengharuskan perpustakaan kesalahan pelanggan saya. Pencitraan melempar kesalahan khusus di mana kesalahan khusus itu tidak terdefinisi.

Juga, jika ini salah maka tolong beri tahu saya karena saya baru saja mulai melakukan ini baru-baru ini

DrunkenBeetle
sumber