node.js express.js 中的全局函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16788807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:37:56  来源:igfitidea点击:

Global function in express.js?

node.jsexpress

提问by nfpyfzyf

How can I define a global function in express.js, that without requireI can call it

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

回答by Andy Brown

"How" is simple enough:

如何”很简单:

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

But you don't need the globalprefix; the thing about the globalobject is ...

但是你不需要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.

"Without require" is a separate consideration: if you don't use requirethere is no guarantee your "globals" will have been declared by the time you need them. It enforces loading order of dependencies, among other things.

“没有require”是一个单独的考虑因素:如果您不使用require,则无法保证您的“全局变量”在您需要它们时已被声明。它强制执行依赖项的加载顺序等。

"Why am I" and "Is it correct to" are now hidden questions you should consider. It is accepted in javascript that Global Variables ...

为什么是我”和“这样做是否正确”现在是您应该考虑的隐藏问题。在 javascript 中接受全局变量 ...

... should be reserved for objects that have system-wide relevance and they should be named to avoid ambiguity and minimize the risk of naming collisions - Angus Croll, Namespacing in Javascript

... 应该保留给具有系统范围相关性的对象,并且应该命名它们以避免歧义并最小化命名冲突的风险 - Angus Croll,Javascript 中的命名空间

i.e. globaltruly is Global: it is used by every author of every plugin or library you pull in to your application, not just you. Naming collisions between global variables break your application. This applies equally in node.js.

ieglobal确实是全局的:它被您引入到应用程序中的每个插件或库的每个作者使用,而不仅仅是您自己。全局变量之间的命名冲突会破坏您的应用程序。这同样适用于 node.js。

Global variables are also thought of as a code smell. In the detail sections below here you will see you can quickly get into trouble by using global variables, and they should really be treated as something that pushes you towards dependency injection and/or namespaces and modules.

全局变量也被认为是一种代码异味。在下面的详细信息部分,您将看到使用全局变量会很快陷入困境,并且它们真的应该被视为推动您进行依赖注入和/或命名空间和模块的东西。

Node.js and express - global vars and functions

Node.js 和 express - 全局变量和函数

Here's a good rule: if you upload it to a web server, or share it with other people, don't use global variables.

这是一个很好的规则:如果您将其上传到 Web 服务器,或与其他人共享,请不要使用全局变量。

globalis permissible in tiny "Saturday afternoon" apps in node.js with express.js, but tend to cause problems later if they get adopted into production. Therefore:

global在带有 express.js 的 node.js中的小型“星期六下午”应用程序是允许的,但如果它们被采用到生产中,则往往会在以后引起问题。所以:

  • Modules and exportsis best practice.
  • Injection should also be used to reduce coupling between javascript files. But in all cases you will usually need requireto ensure they exist by the time you need them:
  • You should really consider app.localsdata, and/or middleware functions, for anything that is view data related.

    // 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()
    
  • 模块和exports最佳实践。
  • 还应该使用注入来减少 javascript 文件之间的耦合。但在所有情况下,您通常需要require确保它们在您需要时存在:
  • 对于与视图数据相关的任何内容,您应该真正考虑app.locals数据和/或中间件函数

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

If you are creating global vars/functions for configuration settings purposes the below comments about namespaces still apply, and there are conventions emerging such as config.json files (still using require) for settings that are globally accessed.

如果您正在创建用于配置设置的全局变量/函数,以下关于命名空间的注释仍然适用,并且出现了一些约定,例如 config.json 文件(仍在使用require)用于全局访问的设置。

Global variables - simple case

全局变量 - 简单案例

It is simple enough to declare a global variable in javascript, and for a function the process is no different. Simply omit the varkeyword which would normally force a local scope on the declaration:

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

But what if two separate plugins in your project use a global getVersionfunction - how do you get the right version number? Also, how do you ensure that getVersionexists before you need it, or exists at all?

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

Why do we need require?

我们为什么需要require

To quote the nodejitsu docs the built in requirefunction...

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

... is the easiest way to include modules that exist in separate files. The basic functionality of requireis that it reads a javascript file, executes the file, and then proceeds to return the exportsobject

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

"So", you may ask, "requirejust makes sure that a modulefrom another file is included? Why bother?"It's better than that: you can make a whole folder a module, making your code easier to organise and test test test, it will recognise various extensions for file modules, not just .js, and it will lookin various folders as well. Of course, it cachesas well.

所以”,您可能会问,“require只是确保包含来自另一个文件的模块?何必呢?” 这是比这更好的:你可以做一个整个文件夹的模块,使您的代码更容易组织和测试测试测试,它可以识别各种扩展模块文件,而不仅仅是.js,它看起来不同的文件夹以及。当然,它也缓存

So, now that requirehas found your module, it ensures the code inside it is executed, and puts the objects your created into a "namespace":

因此,既然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"

In that sample, demoModuleReferenceis an object that looks like:

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

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

Why modules and not global variables (a.k.a namespacing and "Global is the new private")?

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

Seems complicated now? Surely global variables are easier? requiresensures the following:

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

  • It ensures ordered loading of dependencies
  • It prevents variable name conflictswithin globalthrough the exportsobject.
  • 它确保有序加载依赖项
  • 防止了变量名冲突global穿过exports对象。

This application at mankz.com (chrome or firefox only)is fascinating. Depending on how you use your js code, you are very likely to have variable name conflicts within the global scope. Name conflicts come from everywhere. In a browser, for instance, they can come from extensions. node.js is slightly different, but it is becoming more and more extended by compatible plugins as time goes on (you can load jquery in right now, for example). As the versions go on frameworks will get added, and name collisions in global will become more likely. My last run of that app in chrome showed over 1200 global namespace variables.

mankz.com 上的这个应用程序(仅限 chrome 或 firefox)非常吸引人。根据您使用 js 代码的方式,您很可能会在全局范围内发生变量名冲突。名称冲突无处不在。例如,在浏览器中,它们可以来自扩展。node.js 略有不同,但随着时间的推移,它通过兼容插件变得越来越扩展(例如,您可以立即加载 jquery)。随着版本的增加,框架将被添加,并且全局中的名称冲突将变得更有可能。我上次在 chrome 中运行该应用程序时显示了 1200 多个全局命名空间变量。

Namespaces - why?

命名空间 - 为什么?

This global namespace pollution was publicised early on by Douglas Crockford through Eric Miraglia in the article "A JavaScript Module Pattern". In summary:

Douglas Crockford 通过 Eric Miraglia 在“ JavaScript 模块模式文中很早就公开了这种全局命名空间污染。总之:

  • All objects that need to be used between js files are really global
  • So, create a namespace object that will be unique
  • Assign the return value an anonymous function
  • Add private methods and variables inside that function
  • Do something useful with the pattern
  • 所有需要在js文件之间使用的对象都是真正全局的
  • 因此,创建一个唯一的命名空间对象
  • 将返回值分配给匿名函数
  • 在该函数中添加私有方法和变量
  • 用模式做一些有用的事情

Example:

例子:

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

Why is this good?

为什么这很好?

  • Now you have only increased the globalnamespace members in the world by one, but this member contains as many items as you like.
  • Your application is far less likely to clash with other namespaces
  • It's a pattern, other frameworks expect you to use itto interact with them properly. In that reference, jQuery is a browser plugin, but you can use it with node and therefore your app, so the library interactivity policy statement is a perfect example.
  • It's a pattern, if we all follow it weour programs are all more likely to get along
  • 现在您只global将世界上的命名空间成员增加了1,但该成员包含您喜欢的任意数量的项目。
  • 您的应用程序与其他命名空间发生冲突的可能性要小得多
  • 这是一种模式,其他框架希望您使用它来正确地与它们交互。在该参考文献中,jQuery 是一个浏览器插件,但您可以将它与 node 一起使用,从而与您的 app 一起使用,因此库交互策略声明是一个完美的例子。
  • 这是一种模式,如果我们都遵循它,我们的程序就更有可能相处融洽

When you read the Crockford referencealong with the Croll reference(Direct Assignment section) I mentioned at the start, you see why it looks this complicated rather than just doing: sound.play = function() { ... }- ease of maintenance, refactoring the namespace etc. being just one reason.

当您阅读Crockford 参考以及我在开头提到的Croll 参考(直接分配部分)时,您会明白为什么它看起来如此复杂,而不仅仅是这样做:sound.play = function() { ... }- 易于维护,重构命名空间等只是一个原因。

Summary

概括

In summary:

总之:

  • Can I create globals? Yes, it's simple, omit the varkeyword before the declaration.
  • Should I create globals? You should use the module pattern, which is implicitly supported by node, and by express
  • Why am I creating globals? If it's for configuration, use a config namespace (e.g. How to store Node.js deployment settings/configuration files?)
  • 我可以创建全局变量吗?是的,很简单,省略var声明前的关键字。
  • 我应该创建全局变量吗?您应该使用 node 隐式支持的模块模式,并通过 express
  • 我为什么要创建全局变量?如果是用于配置,请使用 config 命名空间(例如,如何存储 Node.js 部署设置/配置文件?

回答by Andreas Hultgren

You can:

你可以:

global.name = function(){};

But you really should avoid using globals, even if it's possible to use them.

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