Using ES6 and Node.js, recommended way to require [duplicate] - javascript

This question already has an answer here:
Is there an efficiency difference between const vs var while 'requiring' a module in NodeJS [closed]
(1 answer)
Closed 7 years ago.
Using ES6, and Node.js, what is the recommend way to require packages let or const?
let _ = require('underscore');
or
const _ = require('underscore');

Unless you plan on ever redefining the package within the scope of your file (or wherever you're requireing) then it's probably best to use const: This will protect against accidental reassignments of the package variable.
For instance:
const _ = require('underscore');
// ...
let [a, _] = foo; // SyntaxError: "_" is read-only
Since we're talking about ES6, const, and require, it makes sense to bring up import statements as well, which for the most part can be thought of as a more flexible version of require. [1]
import _ from 'underscore';
// ...
let [a, _] = foo; // TypeError: duplicate declaration "_"
ES6 imports register as const by default, thus similarly preventing reassignment.
So, when would you want to use let for a require? Let's say (no pun intended) you want to use a special version of a package in certain environments.
let secureLibrary = require('secureLibrary');
// override all security in dev mode
if (process.env['NODE_ENV'] === 'development') {
secureLibrary = secureLibrary.fake;
}
In this contrived example, during development, your use of secureLibrary will be replaced by a fake one, presumably ignoring self-signed SSL certificates or some other convenience that would be unsuitable for production.
In summary: most of the time use const but occasionally let provides necessary flexibility, and consider using import if you're already using ES6!
[1] Please note: under the hood there are many more differences between ES6 import and CommonJS require, please see Using Node.js require vs. ES6 import/export and http://www.2ality.com/2014/09/es6-modules-final.html for many more gory details.

Related

Why ECMAScript ES module import do not follow destructuring standard? [duplicate]

This question already has an answer here:
Relation between import and destructing es6 syntax?
(1 answer)
Closed 11 months ago.
In JavaScript I can rename and imported module this way
import { original_name as alias_name } from 'my_module'
Is there a good explanation for the need of as keyword and nod just follow the excellent destructuring standard?
Why not something like this:
import { original_name: alias_name } from 'my_module'
Just a curiosity always come to my mind
The answer is of course, they are different because they do different things, and only happen to have similarities in syntax.
But maybe there is a better reason why they were designed that way? I experimented with Node.JS modules in the following way:
// origin.js
export let specialNumber = 2;
setInterval(() => {
specialNumber = Math.random();
}, 400)
// importer.js
import { specialNumber as aliasAttempt } from './origin.js'
import * as StarImport from './origin.js'
let { specialNumber: destructuringAttempt } = StarImport;
setInterval(() => {
console.log(aliasAttempt, destructuringAttempt);
}, 400)
Here, destructuringAttempt will always give "2" (the value it got when it was destructured), whereas aliasAttempt will be keep getting changed. For example:
0.3600619094195876 2
0.33268826082163194 2
0.20684912705131553 2
0.8665522020482055 2
0.9349778920742413 2
It looks like destructuringAttempt copied by value during destructuring, whereas aliasAttempt keeps the reference to the let specialNumber variable.
(this behavior of destructuringAttempt is expected as let { specialNumber: destructuringAttempt } = StarImport; is just the same as let destructuringAttempt = StarImport.specialNumber; i.e. just copied the number)
So, maybe the reason was that, if the export is a non-const value, 'aliasing' gives a different result ("keep reference to the other variable") from typical destructuring behavior ("copy once"), therefore it's better to distinguish the syntaxes.
They do different things:
Destructuring is a form of property access, usually combined with a variable declaration like const, and possibly even a default initialiser
Importing a variable does declare an alias for a binding in the module scope
The important difference is that destructuring does run code (test object coercability, execute getters) while import declarations are fully declarative (setting up dependencies between modules, enabling cross-module hoisting even before the variables are initialised). This makes the latter statically analysable. Import aliases also have no concept of nested objects.
Both do allow "renaming", but they use different syntax for different things - it would've been too confusing otherwise. That their shorthand forms are similar to each other is mostly coincidental, caused by both using braces.

Is "import * as" less efficient than specific named imports? [duplicate]

This question already has answers here:
Is using an ES6 import to load specific names faster than importing a namespace?
(3 answers)
Closed 4 years ago.
Suppose I have a module foo like this:
export const f = x => x + 1;
export const g = x => x * 2;
I can use this module like this:
import { f, g } from 'foo';
console.log(f(g(2)));
Or like this:
import * as foo from 'foo';
console.log(foo.f(foo.g(2)));
I prefer the second way because it prevents name collisions between modules.
However, is import * less efficient? Does it prevent bundlers (such as Rollup and Webpack) from spotting unused imports and removing them?
When you specify imports as import { f, g } from 'foo'; you guarantee better performance in terms of speed in compilation and bundle size as you will be getting only the dependencies you need.
Notes: as loganfsmyth pointed out, some recent compiler/bundle are able to reference what actually is being used only, this IMO is an additional step which could cost some compilation time (although I did not have time to benchmark this assumption).
import * is less efficient in that you are using more memory to pull the entire library as opposed to just the specific methods that you actually need
Webpack at least (not sure about Rollup), is perfectly able to see that foo.f is a reference to the f exported name, so your two examples will behave the same.
For most bundlers this does not matter since everything has to be included, 'cause
export const g = (() => {
console.log("Side effects!");
return x => x * 2;
})();

Using const for requiring a module

In one of my NodeJS application , I noticed the below code;
const { Function } = require('./modules/helpers.js')
Is this valid? Also any benefits of using const for the require ?
Yes, destructuring assignment is a valid syntax:
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
({a, b} = {a: 10, b: 20});
console.log(a); // 10
console.log(b); // 20
See: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
EDIT:
As for the benefits, It is a syntax sugar in most of the case. It allows you to refer the import functions directly as Function instead of Helper.Function.
It can also reduce your bundle.js file size.
Making use of const has some big improvements for yourself. So you can't change your imported modules anymore. This imported modules is so called immutable, which is really good for some points. For more have a look over here: Short Introduction into immutable data structures
Edit: const doesn't really mean that a value isn't changeable anymore, but it means that the object at this point can't be reassigned. (Thanks to #Mark Stosberg for pointing that out again)
(simply the code is more easily to reason about and it is about good code style)
And the syntax is valid ES6 destructing syntax. Make sure that your module exports an variable called Function. For more have a look over here: MDN Destruction Syntax

How to alias pseudo-namespaced code using let keyword?

As a beginner in JS, I would like to understand one usage of let declaration, as shown below from MDN,
You can use let definitions to alias pseudo-namespaced code in extensions. (See Security best practices in extensions.)
let Cc = Components.classes, Ci = Components.interfaces;
What is pseudo-namespaced code?
How to alias pseudo-namespaced code using letkeyword?
When dealing with namespaces in Javascript, it can become quickly annoying to always specify the full namespace to access a value or method. For example:
let myModule = {
mySubModule: {
mySubSubModule: {
myMethod: function () {}
}
}
};
// to use myMethod, we need to write the full namespace
myModule.mySubModule.mySubSubModule.myMethod();
By storing the "path" in a variable, we can avoid writing the full namespace each time we need to call myMethod:
let shortcut = myModule.mySubModule.mySubSubModule;
shortcut.myMethod();
I don't really understand why there is a paragraph specifically for Firefox extensions. As long as your browser understands the let keyword of the Ecmascript 6 specification, you are free to use this technique with whatever namespace you want. It also works with the var keyword, although you won't benefit from features like block-scoping.

In javascript should I use const instead of var whenever possible?

If creating a reference to an object, and the reference is not going to change (even though the object will), is it better to use const instead of var?
For example:
const moment = require('moment')
exports.getQuotation = function(value) {
const quotation = {};
quotation.value = value;
quotation.expiryDate = moment().add(7, 'days');
// Do some other stuff with quotation perhaps
return quotation;
};
You can use const, but you have to run node on --harmony
node app.js --harmony
You also have to set "use strict", otherwise you'll have run-time execution issues:
exports.getQuotation = function(value) {
"use strict";
const I_AM_CONSTANT = {};
let quotation = {};
...
Other than that, yes if you are running node on --harmony, semantically it makes more sense to use const for constants. For actual variables you should use let instead of var, as let only defines the variable in the scope (avoids hoisting issues)
If you check MDN, for its reference you can find that its an experimental technology which is part of ES6 proposal. Its browser support is limited.
Reference for const from MDN
This is an experimental technology, part of the Harmony (ECMAScript 6)
proposal. Because this technology's specification has not stabilized,
check the compatibility table for usage in various browsers. Also note
that the syntax and behavior of an experimental technology is subject
to change in future version of browsers as the spec changes.
So this answers whether you should use everywhere. :)
Also if you want to create properties in objects which should not be allowed to change, then you should check Object.defineProperties() and the use of writable attribute.
const is used for a variable constant, i.e. once declared, it's value is not supposed to change, whereas var can be changed as per the will.
Use of const and var is solely on your will. For me it goes as follows
If I'm 100% sure that the value of a variable is not going to change and it's not going to re-declared, I'll define it as a const.
In all other cases I'll use var.
Mind it, re-declaring const will immediately throw an error.

Categories