What qualifies as being a dynamic export in ES6 - javascript

I hear that dynamic exports/imports are not allowed in es6.
This website Uses the example export default 5 * 7; as if it were a legal, static export. This seems reasonable since it clearly evaluates to the static value of 35, but I'm wondering what exactly qualifies as a static export now.
This Code uses export default Backbone.Router.extend({...}); as if it were a legal, static, export. This seems fishy to me as it seems like a dynamic export to me (exporting the result of a function call).

The second example only exports the result of the function call, which is static. The function is only called once, thus the result will always be the same on every import.
An Example to illustrate:
f.js
function f() {
return 2 * Math.random();
}
export default f(); // Is called, before the export is defined. Result: 1.23543
i1.js
import f from 'f';
console.log(f); // 1.23543
i2.js
import f from 'f';
console.log(f); // 1.23543 as well

All exports are static in ES6, that is, their exported name resolves to exactly one variable binding in the exporting module and this can be determined by a single look prior to evaluating of the module code.
A module cannot dynamically add or remove exports through execution of code, the list of exported names is fixed by the declaration.
Whether this variable holds a constant or the result of a function call doesn't matter, neither does whether it holds a primitive value or an object. It doesn't even need to be a constant, the content of the variable may change over time (see an example here).
All imports from import statements are static as well, which means that you can explore the dependency graph without executing any module code.
A dynamic import is done by an explicit call to the module loader. Such loads can depend on the control flow of the module, and may differ from run to run. The code needs to manually handle the asynchrony of the process and potential errors.

You can actually have "dynamic" exports through named exports.
If you do something like this
let awesome = 42;
export { awesome };
you're exporting a binding to the variable and not the value
you can later do this
import { awesome } from './awesome';
awesome = 100;
and any place awesome has been imported will now get the updated value regardless of when awesome was imported
reference: https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/es-next-beyond/ch3.md#exporting-api-members
you can also have dynamic imports
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});
reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

Related

Undertanding JavaScript methods

I am pretty new to JavaScript, coming from a Java background. I was just playing around with the NodeJS ("type": "module") Express framework but got between two types of ways for writing the methods in JS.
Below are the examples (check comments inline).
Type 1:
main.js
const method1 = () => {
...
method2();
...
};
const method2 = () => {
// this is not exported, so it works as a private method and won't be accessible in other JS files
...
};
.
.
.
// likewise there can be many other methods here
export { method1 }; // export other methods as well
Then, I can use the method1 (cannot use method2 as it is not exported) in any other JS file like below:
test.js
import { method1 } from './main.js';
method1();
Type 2:
main.js
class Main {
method1() {
...
method2();
...
}
#method2() {
// this is a private method, so won't be accessible outside of this class
...
}
// likewise other methods here
}
const main = new Main();
export default main;
Then, I can use this class instance in any other JS file like below:
test.js
import main from './main.js';
main.method1();
I want to know what is the difference between these two, when to use which, and which is better.
Both approaches work fine, but Type 2 is somewhat weird because you're using a class only to keep something from being exported.
Classes are usually used to group together data (properties on the instance of the class) with methods that operate on that data. For a silly example:
class NumberMultiplier {
constructor(num) {
this.num = num;
}
multiply(mult) {
return this.num * mult;
}
}
const n = new NumberMultiplier(5);
console.log(n.multiply(10));
Above, there is data (this.num), and there's also a method that operates on the data (multiply).
But in your case, you don't look to have instance data - you only want to group functions together, there's not really a reason to use a class. You can consider defining the functions individually - as you did in the first snippet - or you could use a plain object that gets exported, with only the properties you need:
const method2 = () => {
};
export default {
method1() {
method2();
}
};
If you do have persistent data and want to put it on the class instance, using a class and # private methods is a possibility (creating a single instance with new and then exporting that instance is an example of a singleton).
A potential issue to be aware of is that if you use export default with an object, there's no way to extract a single property of the export when importing in a single line. That is, if you only have a default export, you can't do something like
import { method1 } from './main.js'.default;
You could only do
import theObj from './main.js';
const { method1 } = theObj;
which some would consider to look a bit ugly. Having independent named exports can make it a bit easier for the consumers of a module to import only what they need into standalone identifiers, in a single line.
Classes in JS, unlike your familiarity in Java, are rarely used when not explicitly necessary. Nevertheless, there are situations where OOP in JS could be very useful.
Basically, the first method (Type 1) is what you're going to be using/seeing 99% of the time if you're doing just general JS programming such as front-end websites or apps.
If you're i.e. making a game however, you could use OOP to have better control over the different characters/object in your game.
In terms of back-end or on an infrastructural level, it really depends. You could perfectly use classes (Type 2) if you're following the MVC design pattern, but is again optional.
In the end, it comes down to your own design choice(s). You could go for FP (T1) or OOP (T2) whenever you like in JS, although there are some 'industry standards' for certain scenarios to decide when to use which.
It actually depends on what you are exporting. The type 1 is more appropriate if you export only one or a few objects. With type 1, you can export any primitive type variables or objects and can be used straightaway in the main.js.
However, if you want to export many objects and/or variables, then type 2 makes sense. With type 2, all exports are stored in an object, so you have to access them using this object.
Performance-wise both are same.

How to use javaScript file as Higher Order wrapper for other JavaScript File

I want to ask, as in react we have HOC (Higher order components) where we pass components that modify it and then return modified Component for use
can we do same in javaScript?
for Example
// index1.js
// this is file where i am importing all the folder modules and exporting them
export { methodA, methodB } from './xyzAB'
export { methodC, methodD } from './xyzCD'
i am importing this file in another folder like this
import * as allMethods from './modules'
// this allows me to use this syntax
allMethods.methodA()
allMethods.methodB()
this is working fine, but i am looking for this kind of wrapper
// index2.js
// this is another file somewhere else where i want to use index1.js exported methods
import * as allMethods from './modules/xyz'
import anotherMethod from './somewhere/xyz'
// here i want customize some of `allMethods` functions and export them as new object
//which contains modifed version of default `index1.js` methods
allMethods.methodA = allMethods.methodA( anotherMethod ) // this is example of modified as HO Method
export default allMethods
My Above example may seem confusing,
why i am looking for such solution, i have set of utilities which i am trying to make them as library and use them in multiple projects,
now some of utils are dependent on main project related things, so instead of giving my utilities hard coded reference to their dependencies,
i want to pass different dependencies for different methods through my higher order method or configuration file,
so that each new project pass its dependent utilities from their config or higher order wrapper file as example shown above
I hope i was able to clear my question,
Few things which i tried,
i tried importing all modules in file which i count as wrapper file
in that if i try to use any module that returns webpack error as undefined method, due to methods not loaded fully until few seconds, i tried setTimeOut, that works fine, but this is not valid way of managing thing,
then i tried some async way, i used dynamic import() which returns promise, i used async/await syntax, and also used .then syntax but couldn't extract data and save it as variable (i may be doing something wrong at this step but i was totally failed) but this was only available with in promise or async await scope,
there were also other steps tried,
i am hoping i could find some neater syntax like below
import * as F from '../../core/lib/functions'
import { getModel } from '../entities'
F.getKeys = F.getKeys( getModel )
export default F
any suggestion is welcome
I think what you're looking for is some sort of currying or factory-like pattern.
There is no such thing as higher order modules but since JavaScript support higher order functions that is what you should use.
Just as a reminder, a higher order component is any component that takes a component as a parameter and returns another component. Similarly (simplified) a higher order function is one that takes a function as a parameter and returns a new function. (in reality all React components are more or less functions so thus why we are able to have higher order components).
The key thing is that you need to call a higher order function, not just import it (since again, there is no such thing as a higher order module). But this ties well into your idea of dependency injection.
I think, what you want is something like this in your utilities:
function a(dependency1, arg1, arg2) {}
function b(dependency2, arg1, arg2) {}
function createUtils(dependency1, dependency2) {
return {
a: a.bind(null, dependency1),
b: b.bind(null, dependency2)
}
}
This allows you to customize per project what dependency 1 and 2 are and the details for how they work (with some common interface). With the binding you don't have to pass that dependency in with every call to a function.
Then in one of your projects you'd set them up something like this:
import { createUtils} from 'utils';
import { dependency1, dependency2 } from 'somewhere' ;
const { a, b } = createUtils(dependency1, dependency2)
export { a, b };
You're not really doing any higher order function stuff, like I said this is more like a factory/dependency injection thing. Though bind is a higher order function (it takes the function it's called in and returns a new function with some arguments bound).
You can put place in createUtils for general modifications through another parameter with options. Or you can export smaller "factories" for each method that you want to be able to modify.
With that in mind you might to only export the raw functions from utils and use bind in your module setup code to bind the dependencies. I think bind is what you are missing. As well as that you have to create new functions to export, rather than modifying the imported functions. That also means that your imports in the rest of your code will come only from within your own module, not from the utils module.

Exporting a module object and importing specific properties of said module

I'm writing a JS Module, in which I want to export an object concerning functions declared in the same file.
Ideally, I would like to import only the properties of the exported object, instead of importing the whole object and deconstructing it. Is it possible in some manner?
module.js
export const foo = {
bar: () => console.log("foobar")
}
component.js
import { bar } from './module.js'
bar();
The current problem is that the bar isn't recognized as a function.
I'm writing a JS Module, in which I want to export an object with reference to functions declared on the same file.
There's no reason to have that object. That's what modules are for. The bindings you export become part of a module object (you never get a direct reference to it), so there's no need for you to explicitly create the object — and doing so gets in a the way a bit, and prevents tree-shaking (eliminating code that is never used).
Ideally, I would like to import only properties of the exported object, instead of importing the whole object and deconstructing it.
With your current approach, that's what you have to do, e.g.:
import { foo } from "./module.js";
then to use bar, either use foo.bar(); or destructure:
const { bar } = foo;
bar();
That's because what you've exported isn't bar, it's foo, an object that has a property called bar. Your import should be failing, because there's no named export called foo. (But if you're using a bundler, it may be obscuring that error.)
But again, there's no need for that object. Instead, just do this:
module.js:
export function bar() {
console.log("foobar");
}
or
export const bar = () => {
console.log("foobar");
};
Then your import in component.js will work.

how to make global variable and functions which can be accessible in all the components in angular 4

I am struggling with global variables as I want some variables which I need to access in all the components so what should i do in angular 4.
I've tried something like this:
Created one file with the name of global.ts and made a class with the name GlobalComponent something like this
export class GlobalComponent {
globalVar:string = "My Global Value";
}
and am using it on HeaderComponent by importing and making instance and it's working fine but this is very long process to import in each and every files to get it available.
So I want it to be available on all the components without importing it.
Is there any way or trick to achieve this? Any suggestion would be appreciated :)
As #bgraham is suggesting, it is definitely better to let angular injector to instantiate the service.
But you could also export just a simple object with key-value pairs, including functions. Then you can simply import it and use it (without the instantiation part).
globals.ts file:
export const GLOBALS = {
globalVar: 'My Global Value',
globalFunc: () => alert('123')
};
your.component.ts file:
import { GLOBALS } from './globals.ts';
console.log(GLOBALS.globalVar);
GLOBALS.globalFunc();
Btw I don't think there is a way how to get rid of the import statement - that is part of how typescript works...
I don't think what you want to do is possible and it's probably not a good idea.
The import statements are how webpack (or other bundlers) are able to build a tree to figure out which files to include. So it might be tricky to get global files built into all your bundles.
Also I would add, I'm not sure just importing the static file is the way to go either. It's kind of quick and dirty, which maybe is what you want I guess, but for production apps I would recommend making an angular service and injecting it.
export class GlobalVariablesService {
globalVar:string = "My Global Value";
}
This way you can mock these for unit tests or potentially pass in different variables depending on your changing needs in the future.
If you need these to update and push that into lots of components throughout your app, you might look into Redux. Its pretty handy for that kind of thing.
Sorry, perhaps not the answer you were hoping for
Simply create constant file - constant.ts under src folder.
Now import constant.ts file whenever you require parameter to be called
It will look like so
export const constant = {
COSNT_STRING : 'My Global Value',
}
how to use constant:
1) Import file.
2) constant.CONST_STRING
Also this is a good practice from future prospective, if you want to modify response just made change in one file not in 800 files.

How does an imported module get evaluated in ES6 exactly?

(There is another question of similar title out there but I have a different question here.)
It's stated that in ES6, an imported module is "executed" immediately. However, say for example I have exported an object:
let Player = {
player: null,
init(domId, playerId, onReady) {
window.onYouTubeIframeAPIReady = () => {
this.onIframeReady(domId, playerId, onReady)
}
},
...
}
export default Player
Apparently the object only contains properties and methods. Then, I import it in another module:
import Player from "./player"
How can a series of name-value pairs be "executed" though? To execute the constructor of a class when it's imported makes much more sense (is a class's constructor automatically run when it's imported though? I'm also confused on that), but to "execute" an object just doesn't make much sense to me.
Also, if I import a function from another module, does the function gets immediately "evaluated" and its result produced? This also doesn't seem very right to me since a function sometimes requires arguments, which the importing module doesn't automatically provide any.
Maybe I misunderstood the meaning of the word "execute"/"evaluate" here?

Categories

Resources