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 。
所以,现在require
find你的模块,它确保它内部的代码被执行,并把你创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,即使可以使用它们。