express.js 中的全局函数?
Posted
技术标签:
【中文标题】express.js 中的全局函数?【英文标题】:Global function in express.js? 【发布时间】:2013-05-23 05:35:24 【问题描述】:如何在 express.js 中定义一个全局函数,没有require
我可以调用它
【问题讨论】:
为什么不想用这个函数创建模块? 【参考方案1】:“如何”很简单:
global.fnName = function() return "hi"; ; // Andreas Hultgren's answer
但是你不需要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.
“没有require
”是一个单独的考虑因素:如果您不使用require
,则无法保证您的“全局变量”会在您需要它们时被声明。它强制执行依赖项的加载顺序等。
“我为什么是”和“它是否正确”现在是您应该考虑的隐藏问题。 javascript 中接受全局变量 ...
... 应该为具有系统范围相关性的对象保留,并且应该为它们命名以避免歧义并将命名冲突的风险降至最低 - Angus Croll, Namespacing in Javascript
即global
确实是全球性的:它被您拉入应用程序的每个插件或库的每个作者使用,而不仅仅是您。 全局变量之间的命名冲突会破坏您的应用程序。这同样适用于 node.js。
全局变量也被认为是as a code smell。在下面的详细部分中,您将看到使用全局变量会很快陷入困境,它们应该真正被视为推动您走向依赖注入和/或命名空间和模块的东西。
Node.js 和 express - 全局变量和函数
这里有一个很好的规则:如果您将其上传到网络服务器,或与其他人共享,请不要使用全局变量。
global
在微小的“星期六下午”应用程序in node.js with express.js 中是允许的,但如果它们被采用到生产环境中,往往会在以后引起问题。因此:
exports
是最佳实践。
还应该使用注入来减少 javascript 文件之间的耦合。但在所有情况下,您通常都需要 require
以确保它们在您需要时存在:
对于与视图数据相关的任何内容,您真的应该考虑 app.locals
数据和/或 middleware functions。
// 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()
如果您为配置设置目的创建全局变量/函数,则以下有关命名空间的 cmets 仍然适用,并且出现了一些约定,例如 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"
但是,如果您的项目中的两个独立插件使用全局 getVersion
函数怎么办 - 您如何获得正确的版本号?另外,您如何确保getVersion
在您需要它之前就已经存在,或者根本就存在?
为什么我们需要require
?
引用nodejitsu docs内置的require
function ...
... 是包含存在于单独文件中的模块的最简单方法。
require
的基本功能是读取一个 javascript 文件,执行该文件,然后继续返回exports
对象
“所以”,你可能会问,“require
只是确保包含来自另一个文件的module?何必呢?”那:你可以创建一个whole folder a module,让你的代码更容易组织和测试测试,它会识别file modules的各种扩展,而不仅仅是.js
,它在various folders as well中的will look。当然,it caches 也是如此。
所以,既然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"
在该示例中,demoModuleReference
是一个如下所示的对象:
blah: "foo",
sayHello: [Function]
为什么是模块而不是全局变量(又名命名空间和“全局是新的私有”)?
现在看起来很复杂?全局变量肯定更容易吗? requires
确保以下内容:
exports
对象防止global
内的变量名冲突。
This application at mankz.com (chrome or firefox only) 很迷人。根据您使用 js 代码的方式,您很可能在全局范围内发生变量名称冲突。名称冲突无处不在。例如,在浏览器中,它们可以来自扩展。 node.js 略有不同,但随着时间的推移,兼容插件越来越多地扩展它(例如,您现在可以加载 jquery)。随着版本的继续,框架将被添加,全局名称冲突将变得更有可能。我上次在 chrome 中运行该应用程序时显示了 1200 多个全局命名空间变量。
命名空间 - 为什么?
Douglas Crockford 很早就通过 Eric Miraglia 在文章“A JavaScript Module Pattern”中公开了这种全局命名空间污染。总结:
js文件之间需要用到的所有对象都是全局的 因此,创建一个唯一的命名空间对象 将返回值分配给匿名函数 在该函数中添加私有方法和变量 用模式做一些有用的事情例子:
ANDYBROWNSONICSUITE.BoomBox.SoundModule = function ()
var privateField = "can't touch this";
return
play: function()
console.log(privateField);
为什么这么好?
现在您只将世界上的global
命名空间成员增加了一个,但该成员包含任意数量的项目。
您的应用程序与其他命名空间发生冲突的可能性要小得多
这是一种模式,other frameworks expect you to use it 可以正确地与它们交互。在那个参考中,jQuery 是一个浏览器插件,但你可以use it with node and therefore your app,所以库交互策略声明就是一个完美的例子。
这是一种模式,如果我们都遵循它当您阅读Crockford reference 以及我在开头提到的Croll reference(直接分配部分)时,您会明白为什么它看起来如此复杂,而不仅仅是做:sound.play = function() ...
- 易于维护,重构命名空间等等只是原因之一。
总结
总结:
我可以创建全局变量吗?是的,很简单,在声明前省略var
关键字。
我应该创建全局变量吗?您应该使用 node 和 express 隐式支持的模块模式
为什么要创建全局变量?如果是用于配置,请使用配置命名空间(例如How to store Node.js deployment settings/configuration files?)
【讨论】:
很好的答案-尽管仅供参考,您对命名空间/匿名函数与其余答案之间的关系的意图并不完全清楚。我的意思是你没有明确定义什么时候应该使用模块模式(使用匿名函数):而不是全局变量?或者在使用require的时候?或者在使用 require 制作全局变量时?【参考方案2】:你可以:
global.name = function();
但您确实应该避免使用全局变量,即使可以使用它们。
【讨论】:
我觉得这让人们感到困惑。你不需要'global'来创建全局变量,你只需要省略 var 关键字。我投了反对票。如果您更改此设置,将重新投票。我同意使用像“全球”这样的约定可能是更好的做法,但这需要提及。 如果省略“var”,您的代码将在 scrit 模式下失败“'use strict';”以上是关于express.js 中的全局函数?的主要内容,如果未能解决你的问题,请参考以下文章