express.js中的全局函数?

时间:2013-05-28 09:43:42

标签: node.js express

如何在express.js中定义一个全局函数,没有require我可以称之为

2 个答案:

答案 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。在下面的详细信息部分中,您将看到使用全局变量很快就会遇到麻烦,它们应该被视为推动依赖注入和/或命名空间和模块的东西。

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

如果要为配置设置创建全局变量/函数,则以下有关命名空间的注释仍然适用,并且会出现一些约定,例如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 ...

的nodejitsu文档
  

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

" 所以",您可能会问," require只是确保来自其他文件的module是包括在内呢?为什么要这么麻烦?" 它比这更好:你可以制作一个whole folder a module,让你的代码更容易组织和测试测试,它会识别{{3}的各种扩展} {},而不只是.jsfile 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]
}

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

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

  • 确保有序加载依赖项
  • 通过global对象在exports内阻止变量名称冲突

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

命名空间 - 为什么?

Douglas Crockford在文章" This application at mankz.com (chrome or firefox only)"中通过Eric Miraglia早期公布了这种全球命名空间污染。总结:

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

示例:

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

为什么这样好?

  • 现在,您只将一个global命名空间成员增加了一个,但此成员包含任意数量的项目。
  • 您的应用程序与其他名称空间冲突的可能性要小得多
  • 它是一种模式,A JavaScript Module Pattern可以正确地与它们互动。在该引用中,jQuery是一个浏览器插件,但您可以other frameworks expect you to use it,因此库交互策略声明就是一个很好的例子。
  • 这是一种模式,如果我们都遵循它我们我们的计划更有可能相处

当您阅读use it with node and therefore your app以及我在开始时提到的Crockford reference(直接分配部分)时,您会看到为什么它看起来很复杂而不仅仅是:sound.play = function() { ... } - 轻松维护,重构命名空间等只是一个原因。

摘要

总结:

  • 我可以创建全局变量吗?是的,很简单,在声明之前省略var关键字。
  • 我应该创建全局变量吗?您应该使用节点隐式支持的模块模式,并使用express
  • 为什么要创建全局变量?如果是配置,请使用配置命名空间(例如Croll reference

答案 1 :(得分:11)

你可以:

global.name = function(){};

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