如何在express.js中定义一个全局函数,没有require
我可以称之为
答案 0 :(得分:76)
" 如何"很简单:
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。在下面的详细信息部分中,您将看到使用全局变量很快就会遇到麻烦,它们应该被视为推动依赖注入和/或命名空间和模块的东西。
这是一个很好的规则:如果您将其上传到网络服务器,或与其他人分享,请不要使用全局变量。
global
允许在星期六下午"应用in node.js with express.js,但如果它们被投入生产,往往会导致问题。因此:
exports
是最佳做法。 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()
如果要为配置设置创建全局变量/函数,则以下有关命名空间的注释仍然适用,并且会出现一些约定,例如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
?引用内置require
function ...
...是包含存在于单独文件中的模块的最简单方法。
require
的基本功能是它读取javascript文件,执行文件,然后继续返回exports
对象
" 所以",您可能会问," require
只是确保来自其他文件的module是包括在内呢?为什么要这么麻烦?" 它比这更好:你可以制作一个whole folder a module,让你的代码更容易组织和测试测试,它会识别{{3}的各种扩展} {},而不只是.js
,file modules中的will look。当然,various folders as well也是如此。
所以,既然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
确保以下内容:
global
对象在exports
内阻止变量名称冲突。it caches非常吸引人。根据您使用js代码的方式,您很可能在全局范围内具有变量名称冲突。名称冲突来自各地。例如,在浏览器中,它们可以来自扩展。 node.js略有不同,但随着时间的推移,兼容插件会越来越多地扩展(例如,你现在可以加载jquery)。随着版本继续使用,框架将被添加,并且全局中的名称冲突将变得更加可能。我在chrome中运行的那个应用程序显示了超过1200个全局命名空间变量。
Douglas Crockford在文章" This application at mankz.com (chrome or firefox only)"中通过Eric Miraglia早期公布了这种全球命名空间污染。总结:
示例:
ANDYBROWNSONICSUITE.BoomBox.SoundModule = function () {
var privateField = "can't touch this";
return {
play: function() {
console.log(privateField);
}
}
}
global
命名空间成员增加了一个,但此成员包含任意数量的项目。 当您阅读use it with node and therefore your app以及我在开始时提到的Crockford reference(直接分配部分)时,您会看到为什么它看起来很复杂而不仅仅是:sound.play = function() { ... }
- 轻松维护,重构命名空间等只是一个原因。
总结:
var
关键字。答案 1 :(得分:11)
你可以:
global.name = function(){};
但你真的应该避免使用全局变量,即使它可以使用它们。