我在这里问: Node.js需要继承吗?

我被告知我可以通过省略变量将变量设置为全局作用域。

这对我没用。

也就是说,下面的代码不会使_在必需的文件上可用。

_ = require('underscore');

我可以用Express.js的app.set设置,并在其他地方可用。

这就应该是这样吗?


你可以像这样使用global:

global._ = require('underscore')

在Node.js中,你可以通过"global"或"global"对象设置全局变量:

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

或者更有用的是……

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

从Node.js源代码中,你可以看到它们彼此都有别名:

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

在上面的代码中,“this”是全局上下文。在CommonJS模块系统(Node.js使用的)中,模块内部的“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.js的文件中都这样做,就像在Java中导入com.foo.bar;一样。这让你更容易弄清楚你的代码在做什么,因为文件之间的链接是“显式的”。这有点烦人,但是一件好事. ....这就是说教。

There is an exception to every rule. I have had precisely exactly one instance where I needed to set "GLOBAL._". I was creating a system for defining "configuration" files which were basically JSON, but were "written in JavaScript" to allow a bit more flexibility. Such configuration files had no 'require' statements, but I wanted them to have access to Underscore.js (the entire system was predicated on Underscore.js and Underscore.js templates), so before evaluating the "configuration", I would set "GLOBAL._". So yeah, for every rule, there's an exception somewhere. But you had better have a darn good reason and not just "I get tired of typing 'require', so I want to break with the convention".


我同意使用global/ global名称空间来设置全局内容是一种糟糕的实践,在理论上根本不用它(理论上是有效的词)。但是(是的,操作)我确实用它来设置自定义错误类:

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

global.MyError = [Function of MyError];

是的,这在这里是禁忌,但如果你的网站/项目在整个地方使用自定义错误,你基本上需要在任何地方定义它,或者至少在某个地方:

首先定义Error类 在你扔它的脚本里 在你捕捉它的剧本里

在全局命名空间中定义我的自定义错误,使我省去了需要我的客户错误库的麻烦。成像抛出自定义错误,其中自定义错误未定义。


使用全局命名空间,如global。Myapi = {}:

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

所有其他的海报都在谈论这种糟糕的模式。因此,暂且不讨论这个问题,全局定义变量(OP的问题)的最佳方法是通过名称空间。

提示:使用命名空间进行开发


当项目变大时,使用GLOBAL关键字的其他解决方案对于维护/可读性(+名称空间污染和错误)来说是一场噩梦。这个错误我已经见过很多次了,而且还费了不少周折才改正过来。

使用JavaScript文件,然后使用模块导出。

例子:

文件globals.js

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

module.exports = Globals;

如果你想使用这些,使用require。

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

你可以使用全局对象。

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

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

如果你试图全局访问字符串,我建议使用dotenv:

安装:

npm i dotenv

然后在项目的根目录中创建.env文件,并将所有你想要的变量设置为全局变量,例如:

DB_HOST='localhost'
DB_DATABASE='my_database'
DB_USER='my_user'
DB_PASSWORD='my_password'

ADMIN_EMAIL='foo@bar.baz'
CITY='Some city'
# ... etc

你甚至可以在启动服务器时通过命令行设置这些变量,如下所示:

NODE_ENV=dev PORT=5000 npm run start-dev

此外,如果您使用git,您可能希望将.env添加到.gitignore中,以确保您不会意外提交敏感信息。

然后只需在server.js文件(或任何要执行的第一个文件)的开头包含以下内容

require('dotenv').config()

要在代码中的任何地方使用这些变量,只需使用process.env.VARIABLE_NAME。

例如:

app.listen(process.env.PORT, () => {
    console.log(`Server is running on port ${process.env.PORT}.`)
})

注意:我知道这并没有直接回答这个问题,因为它是关于全局存储字符串而不是Underscore.js,但我认为为了完整性,我会包括它。