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

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.

Related

is there a way to import all keys inside a package with require?

I would like to know if there is a way to import all elements of a package/file without directly naming them
example:
//file1 - things.js
module.exports = {
thing1:{...},
thing2:{...},
thing3:{...}
}
//file2 runner.js
const things = require("./things")
console.log(things.thing1)
//in this case it imports the things.js and its elements and assigns the variable things,
//but that's not what I want
//I want it to import the native variables from the things.js file without having to pull each one individually
//---
//i know i can import the native variables by pulling them like this:
const { thing1, thing2 } = require("./things")
console.log(thing1, thing2)
//but this is not what I want either, what I want should look like the following example:
const {} = require("./things")
console.log(thing1, thing2, thing3)
//imporiting all native variables without having to define one by one
Short answer, no.
When using module.exports, you're effectively assigning a value to the return of require. That value can be any valid JavaScript value, in this particular case, an object. Presently, JavaScript does not have a mechanism for destructuring an object into all of its constituent keys, which is functionally what you're asking for.
In fact, JavaScript has no mechanism at all for implicit variable declaration, at least not in strict mode. If it doesn't appear in the source code, it's not there.
A hacky way around this could be something like this:
const thing = require('../thing.js');
for (const key in Object.keys(thing)) {
global[key] = thing[key]; // using "global" here instead of "window" for environment-agnostic code
}
This will force all of your exports to be available in the global scope, accessible as if they were declared. However, your editor/IDE will get very upset that it doesn't know where these variables came from, and this is horrific, unrecommendable practice.

Difference between class and function blocks in React?

I was going through an article on Commonly faced problems with React and there i found this example.
class Numbers extends React.Component {
const arrayOfNumbers = _.range(1, 10);
// ...
}
It said "The code above is invalid because inside the body of a JavaScript class you don’t have the freedom of doing just about anything. You can only define methods and properties using limited syntax.
This is a bit confusing because the {} used in the class syntax looks like the plain-old block scope, but it’s not.
Inside a function-based component, you DO have the freedom of doing just about anything"
// Totally Okay:
const Number = (props) => {
const arrayOfNumbers = _.range(1, 10);
// ...
};
Can anyone explain to me why the above statement inside the class body is invalid ?? And what is that strange looking _. symbol ??
Can anyone explain to me why the above statement inside the class body is invalid ??
That's just the way the syntax for classes is. You can define functions in the body of the class, and they'll go on the prototype. If you want any instance variables, you do those in the constructor.
And what is that strange looking _. symbol ??
It's a variable named _. In this case, it's almost certainly a reference to the Lodash library, a commonly used library with utility functions.

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

Patterns of CommonJS Modules? [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 5 years ago.
I have been doing some exercises on the interesting "level up your coding" site, Exercism.io and they use the CommonJS style modules for their code samples and testing with Jasmine. I've always thought modules were a hassle I didn't want to deal with, but in these bite size chunks, they look like they could be very useful to begin using in my Single Page Applications. So I've been Googling around and searching Github for some good samples for using CommonJS Modules - and still haven't found one that explains in detail what the main patterns are, and how they differ. For example, one answer I submitted looked like this:
var HelloWorld = function () {};
HelloWorld.prototype.hello = function () {
return 'Hello, World!'
};
module.exports = HelloWorld;
But another one looked like this
var Bob = function () {
this.hey = function (input) {
input = input.split('');
if (input.indexOf('!') >= 0) {return 'Whoa, chill out!'}
if (input.indexOf('?') >= 0) {return 'Sure.'}
return 'Whatever.'
};
}
module.exports = Bob;
Specifically I'm wondering what the difference is between nesting a function inside the parent definition, as done with the Bob hey() function, as opposed to the way the HelloWorld hello() uses the prototype instead.
To start with the two functions you gave as examples are completely different from each other and have different purposes.
Based off of the code you have as an example, the way you are calling them is also incorrect.
For your Bob example, all you are doing is assigning a function to a variable. In order to call it, you simply have to do Bob(). If you do a Bob.hello() you are going to get an error.
The HelloWorld on the other is not just a function, well.. It is, since you declared it as an empty function that is what it will call if you do HelloWorld(). However you defined hello as it's prototype function, for you to invoke that directly you would have to do HelloWorld.prototype.hello(). I reckon that these are used mainly to alter behaviours of existing objects or functions.
You are asking what are the most efficient ways of writing modules, but in reality there is not right answer for that. All a module is is a piece of code that can be exported and reused by other files. They can be functions, objects, simple variables whatever you'd like!
So basically you can do all these:
// moduleThatExportsANumber.js
module.exports = 1
// moduleThatExportsAnObject.js
module.exports = {}
// moduleThatExportsAFunction.js
module.exports = function () { return 'say somethign!'}
// main.js Lets call all the modules!
const number = require('./moduleThatExportsANumber)
const object = require('./moduleThatExportsAnObject)
const function = require('./moduleThatExportsAFunction)
console.log(number) // 1
console.log(object) // {}
console.log(function) // function () { return 'say somethign!'}
console.log(function()) //say somethign!
The whole thing about modules is simply writing stuff in a file, exporting that stuff, which in the case of CommonJS is done through module.exports = [whatever you are exporting], and later importing, which for CommonJS is require('./filename')
Now... Going back to the original thing that was asked, your cheatsheet. I don't know any CommonJS ones unfortunately, however here is a decent blog post about the CommonJS module system and here is a JavaScript one that you may like as well.

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

Categories