In Node, why does 'require' assignment sometimes require curly brackets? - node.js

Running some tests through Chai, I noticed the tests would fail under this code:
const add = require('./addition');
//'add is not a function error' even though it's directly exported as a function
But it would pass under this:
const {add} = require('./addition');
Yet when using npm modules, everything is declared without the brackets:
var express = require('express');
var app = express();
var session = require('express-session');
And those are essentially objects with multiple properties to be accessed. Why does it work this way? Is it only function exports that must be assigned as objects explicitly?

This is known as object destructuring. Please refer the link.
For example you have exported a file called sampleFunctions.js which has following functions as exports
function function1(params) {};
function function2(params) {};
module.exports = {
sampleFunc1: function1,
sampleFunc2: function2
}
Now when you need to require it, there are two ways -
when you only need one function(using object destructuring)
let {sampleFunc1} = require('./sampleFunctions');
sampleFunc1();
In this you exposed only the required function not all of the functions exported from that file.
when you want to require all the functions from that file
let sampleFuncs = require('./sampleFunctions');
let samFunc1 = sampleFuncs.sampleFunc1;
samFunc1()

Related

What do we actually import from Express in a Node.js program

Usually when we import something in Node, we do something like:
const fs = require("fs");
... //use fs's methods for file system stuff
However, when we use express, we are doing:
const express = require("express");
const app = express();
app.get( .... )
What's the difference with the imports? why do we call express() like a function (I'm assuming it imports some function, and if it does, what does the function do)? In case it won't be explained by my previous questions, why don't we call function of the express object we imported?
The export of the express package is a function named createApplication (see here). Calling this function produces an object. I believe it is done this way so that the mixins are produced appropriately at run-time.
Also, keep in mind that in JavaScript, there are no types. Nothing is strictly an object. This function, for instance, has function members.
exports = module.exports = createApplication;
exports.query = require('./middleware/query'); // Assigning a member function to the `createApplication` function.
Because of this, you can call express(), but also call express.query('whatever'). JavaScript is pretty nonsense if you try to interpret it as a well-defined object-oriented language.
Your question makes an incorrect assumption, you say
why don't we call function of the express object
but require("express") returns a Function.
It's a difference in what is exported. One exports an Object with properties attached to it while the other exports a Function.
Express does the latter. See express source:
exports = module.exports = createApplication;
function createApplication() {...};
While node does the former, node fs source:
module.exports = fs = {...};

Can't export function expression: "TypeError: xxx is not a function"

I was trying to follow basic guide on modules. I've created test_module.js
var textFunction = function() {
console.log("text");
};
exports = textFunction;
And then I tried to use it in my app.js:
var textFunction = ('./test_module');
textFunction();
But I get an error:
TypeError: textFunction is not a function
Am I doing something wrong? Or it was a very old guide?
PS: exports works only if I declare it like this:
exports.text = function() {
console.log("text");
}
exports is a local variable. Assigning to it won't change the exported value. You want to assign to module.exports directly:
module.exports = textFunction;
module.exports and exports initially refer to the same value (an object), but assigning to exports won't change module.exports, which is what counts. exports exists for convenience.
The other issue is that you are not properly requiring the module, but that may just be a typo. You should be doing
var textFunction = require('./test_module');
var textFunction = ('./test_module'); just assigns the string './test_module' to textFunction and we all know that strings are not functions.

nodejs require statement issue

I'm new to nodejs. I have the following files and code:
// file: myfunc.js
function myfunc() { return "myfunc()"; }
exports = myfunc;
and
// file: index.js
var mf = require("./myfunc");
var mfunc = mf();
console.log(mfunc);
When I run node index.js from command line, I get the error
var mfunc = mf()
^
TypeError: Object is not a function
Why do I get this error? I saw someone else's code which I paste below and I tried to follow the same approach of trying to get require() to return a function instead of an object.
// file: index.js from another app
var express = require('express');
var app = express();
How come require('express') can return a function but require('./myfunc') can't return a function?
It should be...
module.exports = myfunc;
... instead. Quoting the doc:
If you want the root of your module's export to be a function (such as
a constructor) or if you want to export a complete object in one
assignment instead of building it one property at a time, assign it to
module.exports instead of exports.

Are node.js modules need to be wrapped inside the module pattern?

To ensure proper isolation, I tend to wrap each node.js module that I write inside a function scope:
(function() {
var express = require('express');
var jade = require('jade');
var moment = require('moment');
exports.someFunction = function() {
// do something
};
exports.otherFunction = function() {
// do something else
};
})();
I've been doing this for some time now, but I have the feeling that node.js' module system is actually doing this for me, or (in other words) that the above code is equivalent to the following code:
var express = require('express');
var jade = require('jade');
var moment = require('moment');
exports.someFunction = function() {
// do something
};
exports.otherFunction = function() {
// do something else
};
Are the two really equivalent?
In particular, I am interested to know whether is the isolation level is the same: are the express, jade or moment variables local to the module? (i.e., I'd like to make sure that they are not defined in the global scope or interfere with any other definition outside of this module).
Variables declared within a module are local to that module. It is safe to omit your enclosing function.
From the Node.js docs:
Variables local to the module will be private, as though the module was wrapped in a function

Understanding exports in NodeJS

I don't think I quite understand how exports work in Node.js. In a bit of sample code, I noticed the exports object used in this manner:
exports = mongoose = require('mongoose')
mongoose.connect(config.db.uri)
exports = Schema = mongoose.Schema
What is happening behind the scenes when you use exports = twice like that? Looks to me like "mongoose" should not be exported. I did this quick test:
var foo
, bar
exports = foo = 'foo'
exports = bar = 'bar'
// reports 'bar' only
console.log(exports)
and the second test does overwrite the first export.
My guess is the original author of that sample code is confused about module.exports vs exports. To use the exports object, you must add properties to it like this:
exports.size = 42;
If you re-assign the exports variable to a new object, you basically lose access to the global exports object that node.js provided for you. If you do this twice or three or N times, the effect is the same. It's useless. For example: mod_b.js
var realExports = exports;
realExports.height = 42;
var exports = {};
exports.weight = 43;
And in mod_a.js
var mod_b = require('./mod_b');
console.dir(mod_b);
Run node mod_a.js and you get:
{ height: 42 }
Notice height is there but weight is not. Now, what you can do is assign module.exports to be an object, and that is the object that will be returned when another module requires your module. So you will see things like.
var x = 10;
var y = 20;
module.exports = {x: x, y: y};
Which will do what you expect. Here's some informative articles on the details.
Node.js Module – exports vs module.exports
What is the purpose of NodeJS module.exports and how do you use it?
Mastering Node
As an extension to #Peter-Lyons answer, your example is valid, your test case is incorrect.
Exporting variables like this is not recommended, but by doing that, you are exposing this variables into a global namespace.
e.g. test0.js
'use strict';
var assert = require('assert');
var test1 = require('./test1');
assert(globalVar1 === 123);
assert(globalVar2.a === 123);
test1.js -- mind the missing 'use strict';
exports = globalVar1 = 123;
exports = globalVar2 = {a:123};
Once again, it's valid, but not recommended.
Cheers.

Resources