sharing variables in javascript ES6 without using an import statement? - javascript

I was looking for a javascript implementation of the Astar algorithm that i could steal for my own project, and google immediately led me to bgrins implementation on github:
https://github.com/bgrins/javascript-astar
I copied and pasted his astar.js, and quickly found myself confused on how i was supposed to access the code from my own js module. I took a look at his demo.js file in their repo, and quickly saw that there were no imports. demo.js immediately has access to the astar function as well as the graph object that it takes as a parameter, and i am a little confused by how they managed to accomplish this.
On line 129 of demo.js, they have
this.graph = new Graph(nodes);
without ever using an import statement.
looking closer at the top of astar.js, i see the following code:
(function (definition) {
/* global module, define */
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = definition();
} else if (typeof define === 'function' && define.amd) {
define([], definition);
} else {
var exports = definition();
window.astar = exports.astar;
window.Graph = exports.Graph;
}
})(function () {
Clearly setting window.astar and window.Graph are a part of the answer here, but I find this whole code block a little confusing and very abstract. Can anybody help me to understand what they are doing right here?

Related

HTML/Javascript - Import multiple versions of a js?

Im leaning towards this not being possible, based on all my searching prior to posting this (unless using jquery
Can I use multiple versions of jQuery on the same page?
which i am not) but I figured I would check.
I have come accross a situation where I need one version of socket.io in order for my web application to work, and another version in order to communicate with my python websockets.
Is it possible to use multiple versions of the same js? for instance, one remote, one local:
<script src="/socket.io/socket.io.js" as="ioA"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.6/socket.io.js" as="ioB"></script>
Obviously that itself isnt going to work but I hope it helps illustrate what I want.
If my fear is true that this isnt doable, is there a workaround? Such as containing what I need from the remote one in another js/ejs file, and somehow calling to it from the first page? or will the imports clobber each other.
Apologies if this is a dumb question - haven't come accross this in my limited use of these languages, and can't get a straight answer from my own searches
maybe it would work
<script src="/socket.io/socket.io.js" as="ioA"></script>
<script>
window.antherIO=io;// io refer to the name above.
</script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.6/socket.io.js" as="ioB"></script>
and the local one maybe like this:
function (f) {
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = f()
} else if (typeof define === "function" && define.amd) {
define([], f)
} else {
var g;
if (typeof window !== "undefined") {
g = window
} else if (typeof global !== "undefined") {
g = global
} else if (typeof self !== "undefined") {
g = self
} else {
g = this
}
g.io = f()
}
})(function () {
...
g.io = f()
io set to another name.

RequireJS optimized file returns undefined

We are trying to minify/obfuscate a js library, so that we can reuse it in other projects. Background info: I have done some js, but i'm new with AMD or requireJS.
Here's a reduced version of the library, retaining only the format:
(function (global, factory) {
if ( typeof exports === 'object' && typeof module !== 'undefined'){
factory(exports);
}
else if (typeof define === 'function' && define.amd){
define(['exports'], factory);
}
else{
global['SimpleMath'] = factory({});
}}(typeof global !== "undefined" ? global : self.window || self.global,
(function (exports) {
'use strict';
exports.square = function square(value){
return value * value;
}
exports['square'] = exports.square;
return exports;})));
Inside the main.html we have
requirejs(['./libs/SimpleMath'], function (smath){
console.log(smath);
console.log(require.s.contexts._.defined);
});
This works and we can see the loaded object print out.
Since we wish to optimize/obfuscate the code, we are trying requirejs' optimizer (single js file):
node ../../r.js -o name=SimpleMath out=SimpleMath.min.js baseUrl=.
And we do get something that looks like a minified file.
However, if now I try to load the minified version with the same method:
requirejs(['./libs/SimpleMath.min'], function (smath){
console.log(smath);
console.log(require.s.contexts._.defined);
});
we get 'undefined' for the print out instead.
I can't tell if the original code was wrong, or we are not using the optimizer correctly, or we totally got the concept wrong. Any help or pointers is much appreciated. Thanks in advance.
Answering myself in case someone might find it useful: The minified file was exporting a named module like this
define('SimpleMath',['exports'],t)..
we had to either
load it as a named module with require.config or,
make it anonymous, which seems to be the recommended option for our case.

UMD on sites using RequireJS not working?

When I go to the vast majority of websites, open up the console and paste the following code:
(function(global, appName, app) {
if (typeof define === "function" && typeof define.amd === "object") {
console.log("AMD/RequireJS");
define(app);
console.log("defined app");
} else if (typeof module !== "undefined") {
console.log("CommonJS");
module.exports = app(global);
console.log("defined with module.exports");
} else {
console.log("Browser");
global[appName] = app(global);
console.log("defined as global");
}
})(this, "App", function(global) {
"use strict";
console.log("defining getThis");
function getThis() {
console.log('i got it!');
}
return {
getThis: getThis
};
});
console.log("finished IIFE");
App.getThis();
I get the following output:
Browser
defining getThis
defined as global
finished IIFE
i got it!
If I paste that same code into the console of a site that uses RequireJS such as www.bestbuy.com or www.homedepot.com it fails with this output:
AMD/RequireJS
defined app
finished IIFE
Uncaught ReferenceError: App is not defined at <anonymous>:27:1
I've tried changing the line define(app); to define(['App'], app); with no effect.
I have been googling and puttering around with this for hours now and am at my wit's end. I thought the UMD pattern was UNIVERSAL hence its name. What gives?
Well, it all depends on how are you going to use your script. If you know you are going to use your script in a browser without RequireJS, then it is OK the way you are testing it.
App.getThis();
Because it is in the global object, in the case of a browser, window.
But if you know RequireJS is present, then you need to require your app.
require(["App"], function(App){
App.getThis();
});
And if NodeJS
const App = require('App');
But I've not tested this one.
Also, I recommend you to change define(app); by define(appName, app);
Hope it helps

Call of anonymous function (vanilla js, pure js, no jquery)

I want to grab browser version and OS from useragent via js - this is a practicing example (cause yes - I know - feature detection is how you do it properly ;).
I stumbled across a little library that does so and now I'm trying to understand whats going on.
See this Codepen: http://codepen.io/anon/pen/gPWZGE?editors=001
obviously by running bowser.version - you get the version extracted from the browsers useragent. However the function bowser itself is an anonymous function - even though I can access elements within this function which has to do with this part of the code
!function (name, definition) {
var module;
var define;
if (typeof module != 'undefined' && module.exports) module.exports = definition();
else if (typeof define == 'function' && define.amd) define(definition);
else this[name] = definition();
}
To be honest I have hardly any idea whats going on there - can someone please explain what those lines are doing?
Thanks a lot
Ok, so step by step ...
first you have an IIFE
!function( name, definition ) {
// some code
}( 'bowser', function(){
// your module code
});
this calls the first function immediately with two parameters: the name of the module (here "bowser") and the actual definition function. In that definition function you create the module: You define any objects, properties and whatever else it needs to work. Important point is: You interface (the view the "outside" has on your module, has to be returned by that defintion function (in your codepen this is line 282: return bowser;).
The outer function then determines, how to publish your module:
First it looks for a CommonJS environment:
typeof module != 'undefined' && module.exports
This would be used, e.g., inside NodeJS. If it found the respective objects, it will export your module as a CommonJS module: module.exports = definition().
If this was not a CommonJS environment, the script looks, if it is an AMD (for example, requireJS):
typeof define == 'function' && define.amd
Again, if that matches, the module is exported as a AMD module: define(definition).
Finally, if this is neither CommonJS nor AMD, the script assumes it is a (vanilla) browser or something similar and just attaches the module to the global namespace:
this[name] = definition();
Note, that each time the definition function is called and the return value is exported as a module. This is why your definition function has to return the module interface.

Universal module definition - writing style

It took me a long time to understand this pattern at first, and I think it is mostly because of the way that it is written:
(function(root, factory) {
// Export MyModule depending on the environment
if (typeof define === "function" && define.amd) {
define("MyModule", [], factory);
} else {
root.MyModule = factory();
}
}(this, function() {
return {
// Module definition
};
}));
Isn't that the exact same thing as this?
(function(root) {
var factory = function() {
return {
// Module definition
};
};
// Export MyModule depending on the environment
if (typeof define === "function" && define.amd) {
define("MyModule", [], factory);
} else {
root.MyModule = factory();
}
}(this));
There is a var statement now, but I find this much easier to read. Am I missing something here? Is there a good reason to use the first approach?
Isn't that the exact same thing as this?
Not exactly - those root and factory variables are now in the scope of the module definition, it is one closure level deeper. And this has the grave disadvantage that factory cannot (trivially) be garbage-collected any more, while in the first pattern it was really anonymous.
I find this much easier to read
I disagree. AMD and UMD resolve around a single "define" wrapper that is called with a factory - where the contents of the factory function are the interesting ones (the "main" content of the file) and the definition call is nothing more but a header. This becomes especially obvious when the header is minified and takes only a single line.
In contrast, in the proposed alternative the module is hidden somewhere deep in that IEFE - it even needs to be indented one more level than normally.

Categories

Resources