express.js中的全局函数?

nfp*_*zyf 32 node.js express

如何在express.js中定义一个全局函数,没有require我可以调用它

And*_*own 85

" 如何 "很简单:

    global.fnName = function(){ return "hi"; }; // Andreas Hultgren's answer
Run Code Online (Sandbox Code Playgroud)

但是你不需要global前缀; 关于global对象的事情是......

    fnName = function(){ return "hi"; }; // i.e. don't do: var name = function(){ ... };
    console.log(fnName());         // this prints "hi"
    console.log(global.fnName());  // this also prints "hi" - it was assigned to global.
Run Code Online (Sandbox Code Playgroud)

"没有require"是一个单独的考虑因素:如果你不使用require,则无法保证你的"全局"将在你需要时宣布.除其他外,它强制执行依赖项的加载顺序.

" 为什么我 "和" 它是否正确 "现在是你应该考虑的隐藏问题.在javascript中接受全局变量...

...应该保留给具有系统范围相关性的对象,并且应该命名它们以避免歧义并最小化命名冲突的风险 - Angus Croll,Javascript中的命名空间

global真正的全球:每个插件或图书馆的每位作者都会使用它,而不仅仅是你.全局变量之间的命名冲突会破坏您的应用程序.这同样适用于node.js.

全局变量也被认为是代码气味.在下面的详细信息部分中,您将看到使用全局变量很快就会遇到麻烦,它们应该被视为推动依赖注入和/或命名空间和模块的东西.

Node.js和express - 全局变量和函数

这是一个很好的规则:如果您将其上传到Web服务器,或与其他人共享,请不要使用全局变量.

global在带有express.js的node.js中的小型"星期六下午"应用程序是允许的,但如果它们被采用到生产中,往往会导致问题.因此:

  • 模块并且exports是最佳实践.
  • 注入也应该用于减少javascript文件之间的耦合.但在所有情况下,您通常需要require确保它们在您需要时存在:
  • 对于与视图数据相关的任何内容,您应该真正考虑app.locals数据和/或中间件函数.

    // call this as a function with an input object to merge 
    //  the new properties with any existing ones in app.locals
    app.locals.({
      sayHello: function() { return "hi"; }
    });    
    
    // now you can also use this in a template, like a jade template
    =sayHello()
    
    Run Code Online (Sandbox Code Playgroud)

如果要为配置设置创建全局变量/函数,则以下有关命名空间的注释仍然适用,并且会出现一些约定,例如config.json文件(仍在使用require),用于全局访问的设置.

全局变量 - 简单案例

在javascript中声明一个全局变量很简单,对于一个函数,该过程也没有什么不同.只需省略var通常会在声明上强制使用本地范围的关键字:

// app.js
blah = "boo";
sayHello = function(string toWho) { return "hello " + toWho; }
getVersion = function() { return "0.0.0.1"; }

// routes/main.js
console.log(blah);                     // logs: "boo"
console.log(global.blah);              // logs: "boo"
console.log(sayHello("World"));        // logs: "hello World"
console.log(global.sayHello("World")); // logs: "hello World"
console.log(getVersion());             // logs: "0.0.0.1"
Run Code Online (Sandbox Code Playgroud)

但是如果项目中的两个独立插件使用全局getVersion函数怎么办 - 如何获得正确的版本号?另外,如何确保getVersion在您需要之前存在或存在?

我们为什么需要require

引用nodejitsu docs内置require函数 ...

...是包含存在于单独文件中的模块的最简单方法.它的基本功能require是它读取一个javascript文件,执行该文件,然后继续返回该exports对象

" 那么 ",你可能会问," require只是确保包含来自另一个文件的模块?为什么要这么麻烦?" 它比这更好:你可以将整个文件夹作为一个模块,使你的代码更容易组织和测试测试,它将识别文件模块的各种扩展,而不仅仅是.js,它也各种文件夹中查找.当然,也会缓存.

所以,现在require找到了你的模块,它确保执行它内部的代码,并将你创建的对象放入"命名空间":

// module file ./myModule.js
exports.blah = "boo";
exports.sayHello = function(string toWho) { return "hello " + toWho; }

// routes/main.js
var demoModuleReference = require('./myModule.js');
console.log(demoModuleReference.blah);           // logs: "boo"
console.log(demoModuleReference.sayHello("World"));   // logs: "hello World"
Run Code Online (Sandbox Code Playgroud)

在该示例中,demoModuleReference是一个看起来像这样的对象:

{
  blah: "foo",
  sayHello: [Function]
}
Run Code Online (Sandbox Code Playgroud)

为什么模块而不是全局变量(又名命名空间和"全局是新私有")?

现在似乎很复杂?当然全局变量更容易?requires确保以下内容:

  • 它确保顺序加载依赖项
  • 防止了变量名冲突global穿过exports对象.

此应用程序在mankz.com(仅限chrome或firefox)非常吸引人.根据您使用js代码的方式,您很可能在全局范围内具有变量名称冲突.名称冲突来自各地.例如,在浏览器中,它们可以来自扩展.node.js略有不同,但随着时间的推移,兼容插件会越来越多地扩展(例如,你现在可以加载jquery).随着版本继续使用,框架将被添加,并且全局中的名称冲突将变得更加可能.我在chrome中运行的那个应用程序显示了超过1200个全局命名空间变量.

命名空间 - 为什么?

Douglas Crockford在文章" A JavaScript Module Pattern "中通过Eric Miraglia早期公布了这种全局名称空间污染.综上所述:

  • 需要在js文件之间使用的所有对象都是全局的
  • 因此,创建一个唯一的命名空间对象
  • 为返回值分配匿名函数
  • 在该函数中添加私有方法和变量
  • 做一些有用的模式

例:

ANDYBROWNSONICSUITE.BoomBox.SoundModule = function () {
  var privateField = "can't touch this";
  return {
    play: function() {
      console.log(privateField);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

为什么这样好?

  • 现在,您只增加了global一个世界中的命名空间成员,但此成员包含任意数量的项目.
  • 您的应用程序与其他名称空间冲突的可能性要小得多
  • 这是一种模式,其他框架希望您使用它来正确地与它们进行交互.在该引用中,jQuery是一个浏览器插件,但您可以将它与节点和应用程序一起使用,因此库交互策略声明就是一个很好的例子.
  • 这是一种模式,如果我们都遵循它,我们的程序更有可能相处

当您阅读Crockford引用以及我在开始时提到的Croll引用(直接赋值部分)时,您会看到为什么它看起来很复杂而不仅仅是:sound.play = function() { ... }- 易于维护,重构命名空间等只是一个原因.

摘要

综上所述:

  • 我可以创建全局变量吗?是的,很简单,var在声明之前省略关键字.
  • 我应该创建全局变量吗?您应该使用节点隐式支持的模块模式和express
  • 我为什么要创建全局变量?如果是配置,请使用config命名空间(例如,如何存储Node.js部署设置/配置文件?)


And*_*ren 11

您可以:

global.name = function(){};
Run Code Online (Sandbox Code Playgroud)

但你真的应该避免使用全局变量,即使它可以使用它们.

  • 我觉得这让人很困惑.您不需要'global'来创建全局变量,您只需要省略var关键字.我贬低了.如果你改变它会重新upvote.我同意使用像'global'这样的惯例可能是更好的做法,但这需要提及. (5认同)