express.js中的全局函数?

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

如何 ”很简单:

  global.fnName = function(){ return "hi"; }; // Andreas Hultgren's answer 

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

  fnName = function(){ return "hi"; }; // ie 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. 

“没有require ”是一个单独的考虑因素:如果你不使用require那么就不能保证你的“全局variables”会在你需要的时候被声明 。 它强制加载依赖关系的顺序等等。

为什么我 ”和“ 是否正确 ”现在是你应该考虑的隐藏的问题。 它被接受在JavaScript中,全局variables…

…应该保留用于具有系统相关性的对象,并且应该命名它们以避免含糊不清,并最大限度地降低命名冲突的风险 – Angus Croll,Javascript中的命名空间

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

全局variables也被认为是一种代码味道 。 在下面的细节部分中,您将看到使用全局variables可能会很快陷入困境,并且应该将它们视为将您推向dependency injection和/或名称空间和模块的东西。

Node.js和express – 全局variables和函数

这是一个很好的规则:如果你把它上传到Web服务器,或与其他人共享,不要使用全局variables。

node.js中的小型“周六下午”应用程序可以使用express.js进行 global ,但如果它们被采纳到生产环境中,则往往会导致问题。 因此:

  • 模块和exports是最好的做法。
  • 还应该使用注入来减lessJavaScript文件之间的耦合。 但是,在所有情况下,您通常需要确保在您需要时存在它们:
  • 您应该真正考虑app.locals数据和/或中间件function ,以查看与数据相关的任何内容。

     // 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() 

如果您正在为configuration设置目的而创build全局variables/函数,则有关名称空间的下列评论仍然适用,并且会出现诸如config.json文件(仍然使用require )的约定用于全局访问的设置。

全局variables – 简单的情况

在javascript中声明一个全局variables已经足够简单了,对于一个函数来说,这个过程并没有什么不同。 简单地省略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" 

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

为什么我们需要?

引用nodejitsu文档中内置的require函数

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

所以 ”,你可能会问,“ 只要确保包含另一个文件中的模块 ,为什么呢?” 比这更好:你可以把整个文件夹作为一个模块 ,使你的代码更容易组织和testingtesting,它会识别文件模块的各种扩展,而不仅仅是.js ,它也会在不同的文件夹中 查找 。 当然, 它也caching 。

所以,现在requirefind你的模块,它确保它内部的代码被执行,并把你创build的对象放到一个“命名空间”中:

 // 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" 

在该示例中, demoModuleReference是一个如下所示的对象:

 { blah: "foo", sayHello: [Function] } 

为什么模块而不是全局variables(又名命名空间和“全球是新的私人”)?

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

  • 它确保有序的加载依赖关系
  • 它通过exports对象防止 global variables名称冲突

mankz.com上的这个应用程序(仅适用于Chrome或Firefox)令人着迷。 根据你如何使用你的js代码,你很可能会在全局范围内产生variables名称冲突。 名称冲突来自世界各地。 例如,在浏览器中,它们可以来自扩展。 node.js略有不同,但是随着时间的推移,兼容插件越来越多地被扩展(例如,你现在可以加载jquery)。 随着版本的发展,框架将被添加,并且全球名称冲突将变得更加可能。 我最后一次使用chrome显示了超过1200个全局命名空间variables。

命名空间 – 为什么?

Douglas Crockford在Eric Miraglia的文章“ JavaScript模式模式 ”中早就公布了这种全球命名空间污染。 综上所述:

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

例:

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

为什么这很好?

  • 现在你只增加了global名字空间成员,但是这个成员包含尽可能多的项目,只要你喜欢。
  • 您的应用程序与其他名称空间的冲突的可能性要小得多
  • 这是一种模式, 其他框架期望您使用它来正确地与它们交互。 在这个参考文献中,jQuery是一个浏览器插件,但是您可以将其与节点以及您的应用程序一起使用 ,因此库交互策略语句就是一个很好的例子。
  • 这是一种模式,如果我们都遵循这一模式, 我们的计划就更有可能相处

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

概要

综上所述:

  • 我可以创build全局variables吗? 是的,很简单,在声明之前省略var关键字。
  • 我应该创build全局variables吗? 你应该使用模块模式,这是由节点隐式支持,并通过expression
  • 为什么我要创build全局variables? 如果是用于configuration,请使用configuration名称空间(例如, 如何存储Node.js部署设置/configuration文件? )

您可以:

 global.name = function(){}; 

但是你真的应该避免使用全局variables,即使可以使用它们。