Converting closure to es6 module
I am using a javascript build environment that supports es6 modules ( using es6-module-transpiler ), so you can just import stuff across different files.
I now have a third party library that I would like to "import".
The library fills in its functions as follows:
(function () {/*...*/}).call(this);
It would be safe to omit the closure and convert it to:
export default function () {/* ... */};
Or is there a better way?
Thanks in advance!
source to share
In the source code you show, calls an anonymous function that makes some sense should define a global variable, whereas the second piece of code you show just exports the function, which is completely different.
For purposes of discussion, let's assume the source code defines a global value:
// my-third-party-module.js
(function() {
let myVar = 22;
window.MyThirdPartyModule = { log: function() { console.log(myVar); } };
}.call(this);
and you use it like this:
// app.js
MyThirdPartyModule.log();
You can rewrite this as
// my-third-party-module.js
let myVar = 22;
export default { log: function() { console.log(myVar); } };
// app.js
import MyThirdPartyModule from `my-third-party-module';
MyThirdPartyModule.log();
Note that we have moved the variable myVar
that was local to the anonymous function at the top level of the module.
However, depending on your preference, rather than exporting a LOB, which is a kind of pre-modular mentality, you can export its API separately:
// my-third-party-module.js
let myVar = 22;
export function log { console.log(myVar); }
// app.js
import {log} from `my-third-party-module';
log();
or if you prefer
// app.js
import * as MyThirdPartyModule from `my-third-party-module';
MyThirdPartyModule.log();
However, all of these approaches assume that you can and want to edit the source of the third party library. If not, you can write a small piece of glue code like
// my-third-party-module-interface.js
import 'my-third-party-module'; // This will run the module.
export default MyThirdPartyModule; // Export the global it defined.
// app.js
import MyThirdPartyModule from 'my-third-party-module-interface';
If you'd rather re-export the individual APIs, you can extend the glue to re-export each one:
// my-third-party-module-interface.js
import 'my-third-party-module'; // This will run the module.
const {log, otherAPI, ...} = MyThirdPartyModule;
export {log, otherAPI, ...};
// app.js
import {log} from 'my-third-party-module-interface';
Converting legacy dependencies is still a problem. And the horrible workflow they use makes things a lot harder, prefixing the actual code with the browser and webpack silliness.
So what to do? Existentially the library is only guaranteed to bring in a global window, but it's unclear and weird. And everyone is a little different.
So let legacy just do what it should do for you, but wrapped in a module so you can import it rather than using a script tag:
https://medium.com/@backspaces/es6-modules-part-2-libs-wrap-em-up-8715e116d690
source to share