Use `module` as a namespace

I use a template in my node.js modules that seem so obvious to me that I assume that something is wrong with it, or I will see more people who do it. To save private variables that are global to the module, I simply add them as properties of the module object. For instance:

module.exports = { init: function() { module.someClient = initializeSomethingHere() }, someMethod: function(done) { module.someClient.doSomething(done) } } 

It seems to me preferable to something like this ...

 var someClient; module.exports = { init: function() { someClient = initializeSomethingHere() }, someMethod: function(done) { someClient.doSomething(done) } } 

... because in the second example you need to look for var someClient at the top of the file to avoid var someClient keyword in the init method. I have never seen this template used elsewhere, so I wonder if I am missing something that makes it less ideal.

Thoughts?

+5
source share
2 answers

There are several possible flaws that come to mind.

1) It is technically possible that these properties are accessible and changed outside the module, but only if the link to the module itself is available outside it. What makes a module accessible through its own export ( module.exports = module; which is the simplest example), will expose them.

2) You may have a name conflict with a built-in property or a future built-in property that does not exist yet (which could lead to your code breaking in future versions of node.js). This can be very problematic and very difficult to debug. Currently, the built-in properties of a module object are: children, exports, filename, id, loaded, paths, and parent .

because in the second example, you need to look for var someClient at the top of the file to make sure that the var keyword exception is intentionally in the init method.

If this is the reason, you can simply use a namespace that is not module . For example, adding var private = {}; at the beginning of each file, and then using private.someClient instead of module.someClient .

Also 'use strict'; , so the random omission of var is a mistake, not a random global one.

+4
source

disadvantages

  • Option 1: this practice is prone to naming a conflict with an inline property or a future inline property that does not yet exist, as @paulpro stated in his answer.

  • Option 2: If you missed the var keyword and someClient around the world. In addition, you need to constantly search for var someClient at the top of the file.

Alternative

Because JavaScript has a scope function, it's best to define everything inside the function. Create private and public members within a function. Below is a design template that you can execute:

 'use strict'; module.exports = (function(){ //private var someClient; //public properties var that={}; that.init = function() { someClient = initializeSomethingHere() }, that.someMethod: function(done) { someClient.doSomething(done) } //expose only the required methods return that; })(); 

Only public methods that are bound to this object are available here. And everyone else is closed to the function area. Even if you skipped the var keyword in someClient , it will not be accessible from the side of the function, which will never happen if you use 'use strict' at the top.

Logic the first time you need the xyz.js file, it will return that , not a function.

+1
source

Source: https://habr.com/ru/post/1246512/


All Articles