I'm using a javascript build environment that supports es6 modules (using es6-module-transpiler) so you can simply import stuff across different files.
Now I got a third party library that I'd like to be "importable".
The library populates its functionality like this:
(function () {/*...*/}).call(this);
Would it be safe to omit the closure and convert it to:
export default function () {/* ... */};
Or is there a better way?
Thanks in advance!
The original code you show invokes the anonymous function, which to make any sense must define a global variable, whereas the second code fragment you show merely exports the function, which is a different thing.
For purposes of discussion, let's assume the original code defines a global like this:
// my-third-party-module.js (function() { let myVar = 22; window.MyThirdPartyModule = { log: function() { console.log(myVar); } }; }.call(this);
and you are using is as so:
// app.js MyThirdPartyModule.log();
You could 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
which was local to the anonymous function to the top module level.
However, depending on your preferences, rather than exporting a big object, which is sort of a pre-module mentality, you might want to export its APIs individually:
// 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 you are able and willing to edit the source of the third party library. If that is not the case, you could write a little piece of glue code, such as
// 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 would prefer again to export individual APIs, you could extend the glue to re-export each of them:
// 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';
The conversion of legacy dependencies is still an issue. And the horrible workflow they use makes things a lot harder, prefixing the actual code with browserify and webpack silliness.
So what to do? Existentially, the library is guaranteed only to deposit a global in window but by obscure and weird ways. And all slightly different.
So let the legacy simply do what it is supposed to do for you, but wrapped in a module so that you can import it rather than use a script tag:
https://medium.com/@backspaces/es6-modules-part-2-libs-wrap-em-up-8715e116d690