This requireJS thing has me confused - javascript

Hi i am trying to understand this steganography tool https://github.com/petereigenschink/steganography.js.
I am using this in my react project. The bit about RequireJS has me already confused. Can i turn this to a normal, not so scary javascript?
;(function (name, context, factory) {
// Supports UMD. AMD, CommonJS/Node.js and browser context
if (typeof module !== "undefined" && module.exports) {
module.exports = factory();
} else if (typeof define === "function" && define.amd) {
define(factory);
} else {
context[name] = factory();
}
})("steg", this, function () {}
I need to be able to use this function or whatever it is in my App.js file. Any pointers please?
This is the error that react dev server throws:
Failed to compile.
./src/steganography.js
Line 12: 'define' is not defined no-undef
Line 13: 'define' is not defined no-undef

Since javascript didn't originally include any way of doing modules (ie, to link together code from multiple files), several different approaches have been invented for ways to do so. That block of code is just trying to conform to all of them, so that the codebase will work regardless of which module approach the consumer is using.
The outer part is an Immediately Invoked Function Expression. This is an anonymous function which gets created and then immediately called. In this code, its main purpose is to isolate any variables inside the expression, and thus make it impossible for them to accidentally become global variables.
Inside the IIFE, it has some checks to figure out what kind of module system is being used, so that it can produce the correct output to be imported.

Related

THREE.js TypeError: 'global' is undefined in Firefox

So I tried to include threejs as a drop-in script into my code. No webpack, no browserify, no requirejs. Just a simple gulp/browsersync serve.
I load an external angular app and extend it. Now I need my own THREEjs Version within the codebase.
It gets loaded - but right in the first line they try to set the variable 'global' which doesn't seem to be defined. What am I missing?
// edit:
I am using a js api from another company. I don't know if they set the 'global' var, but Threejs definitely tries to use the var 'global' although I don't use it in a node setup. but in all examples it just works as a drop-in script.
If I use the minified version the error changes to
TypeError: global is undefined
*three.min.js:2:168
anonymous
https://localhost:9000/scripts/three.min.js:2:168
anonymous
https://localhost:9000/scripts/three.min.js:2:2*
and this originates from the following first lines of the three.js file:
function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.THREE = {}))); }(this, (function (exports) { 'use strict'; ...
//EDIT 2:
I finally maaged to find the error which is causing all this.
if youre using gulp-babel and include scripts with that snippet on top, babel tries to replace THIS with the current context, which is - of course - undefined. and thats why bable literally replaces this with undefined. so: never babel() your final vendor files!
The part of THREE.js that you show in your question is not a problem. If we focus only on the problem you've been having, and eliminate the code for the CommonJS and AMD cases, it boils down to this:
(function (global, factory) {
factory(global.THREE = {});
}(this, (function (exports) { 'use strict';
// ...
})));
This is a common pattern. Note that the first anonymous function is called with this as the first argument. So global is set to the value that this has in the global space. If the code above executes in a top-level execution context, then this will automatically have the value of the global object for the environment in which you run the code. In Node, that object is named global. So open a Node session and type:
global === this
You'll get true. In a browser the global object is named window. Open the console in debugging and type:
window === this
You'll get true. So what the code snippet with the anonymous function does is that it uses this to grab a reference to the global object irrespective of where the code executes. It does not have to check whether window exits or global exist, or self or anything else. Instead, it just passes this to the anonymous function and, this way, automatically gets a reference to the global object. There's nothing wrong with that method. It is super common and generally works.
However, it is possible to prevent the code from working properly. For instance if the code above is wrapped in another function and that function uses "use strict", then this will be undefined, and global will be undefined too. Here's an example:
(function() {
"use strict";
(function(global, factory) {
console.log("XXX", global); // You'll get "XXX undefined" here
}(this, (function(exports) {
'use strict';
})));
}());
Sometimes, build processes or code loading tools add such wrapping code, and then they mess up the original code.
Since "just getting babel to ignore certain files" is by no means trivial when working in gulp, a quick and dirty fix for this error is to swap this with window on the 5th line of three.js:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.THREE = {})));
}(window, (function (exports) { 'use strict';
Is this what you need? Just add this one-liner at the very head of your code, in the global scope:
if (typeof global === "undefined"){global=window;}
This is going to reference the global object to the window object, which is the object containing all global variables in browser.

Using functions from external JavaScript libraries in Moodle plugins

I am making a Moodle plugin and wanted to use bowser to detect the user's web browser. I referenced the file by putting
$PAGE->requires->js( new moodle_url($CFG->wwwroot.MOODLE_TINYMCE_RECORDRTC_ROOT.'tinymce/js/bowser.js') );
in the plugin's plugintype_pluginname.php file (placeholders of course), and I call the bowser function from the plugin's module.js file.
When I load the plugin (it appears as a button in TinyMCE), the console throws ReferenceError: bowser not defined, so I'm assuming this means Moodle doesn't make the functions in Bowser globally available.
I read many in many places that I need to wrap my code in an AMD, or something to that effect, but after lots of reading it still goes over my head. Is there any way to make bowser's functions available to the main plugin module?
Note: This works for me in Moodle 3.3.2, ymmv.
Put bowser.js into my_plugin_folder/amd/src/.
When using the original bowser.js I got Uncaught TypeError: bowser._detect is not a function. I don't exactly understand why I get this error but here's one way to fix it: Replace the top code block in bowser.js with this one from umdjs/umd.
Your file should now look like this:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.returnExports = factory();
}
}(typeof self !== 'undefined' ? self : this, function () {
// module definition here
return bowser
}));
Moodle bundles all JavaScript modules together so that clients don't need to perform a separate HTTP request to get each one. This bundle is called first.js. It contains all modules that aren't lazy-loaded. If you load a Moodle page now it should contain the contents of bowser.js with some values replaced by Moodle.
If you don't want bowser to be loaded on every page, you can just rename it to bowser-lazy.js. Then it should only be loaded when you use it.
You can test if it worked by calling:
require(['plugintype_pluginname/bowser'], function(bowser) {
var ua = bowser._detect(navigator.userAgent);
console.log(ua);
});
Seems like you need to change the require call to use bowser-lazy instead of bowser when you want to use lazy-loading.

Building a JavaScript library, why use an IIFE this way?

I have noticed a lot of libraries use this style below to define their library. I also notice that the first self invoking function has something to do with Require.js or AMD systems, they always have factory as an argument, I will look more into Require.js, always been into Browserify.
Why is the main code passed into the end of the first self invoking function inside parentheses, is this is a closure, or just considered an anonymous function, I will dig deeper into both. What are the benefits to this? It looks like inside the closure the author passes a string, this, and a callback.
Will this give my library a clean safe way to globalize the main object in this example below Please?
(function( globalName, root, factory ) {
if ( typeof define === 'function' && define.amd ) {
define( [], factory );
}
else if ( typeof exports === 'object' ) {
module.exports = factory();
}
else{
root[globalName] = factory();
}
}('Please', this, function(){
I am trying to dig really deep into JavaScript and create my own small MVC architecture, I don't want to hear I am silly or its been done before, I want to challenge myself and learn.
If there are any great resources for creating a JavaScript library or even better an MVC library I would love to know.
This code pattern is called Universal Module Definition (UMD). It allows you to make your JavaScript library usable in different environments. It provides three ways of defining modules:
Asynchronous Module Definition (AMD), implemented by RequireJS and Dojo Toolkit.
define( [], factory );
CommonJS — NodeJS modules.
module.exports = factory();
Assigning module to the global object, for example window in browsers.
root[globalName] = factory();
The IIFE has three parameters: globalName, root and factory.
globalName is the name of your module. It applies only to the third way of defining a module, i.e. assigning your module object to the global variable. For example, if you set this parameter to "myAwesomeModule" and use the code in browser (without AMD), you can access your module using myAwesomeModule variable.
root is the name of global object. Obviously, it also applies only to the third way of defining a module. Usually this is passed as this parameter, because this is a reference to window in browser. However, this doesn't work in strict mode. If you want your code to work in strict mode, you can replace this with typeof window !== "undefined" ? window : undefined.
Finally, factory is an anonymous function, which should return your module as object.
See also:
What is the (function() { } )() construct in JavaScript?
What Is AMD, CommonJS, and UMD?
This is an example of Universal Module Definition (UMD). It is a technique to make a JS module compatible with the three popular JS module specs:
Asynchronous Module Definition (AMD, used by Require.js)
define('name', [ /* dependencies */ ], factory);
CommonJS (Node.js ecosystem)
module.exports = object;
Global exports (for example, on window in the browser)
global['name'] = object;
UMD wraps a factory function responsible for creating the object to be exported and passes it as an argument to an immediately invoked function expression (IIFE), as in the snippet you pasted. The IIFE is responsible for detecting the module environment, and exporting the object created by the factory in an appropriate way. The pattern is as follows:
(function (name, root, factory) {
// detect the module environment and
// export the result of factory()
})('name', this, function () {
// module code
// return the object to be exported
});
Many transpilers and build tools generate this wrapper automatically.

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.

What is the purpose of this eval conditional?

I was browsing through the source code here: http://js-dos.com/games/doom2.exe.html and noticed a few things:
if (typeof Module === 'undefined')
{
Module = eval('(function() {try { return Module || {} } catch(e) { return {} }})()');
}
The Module function is defined with an inline script tag
It is later declared again with var in another inline tag, this time it checks if the Module exists.
My question: What is the point of declaring Module with a self invoking function if it'll only try to return the Module again? Hasn't it already been proven that it doesn't exist? Why not just explicitly declare Module as {}?
typeof Module might be undefined if Module is a local variable that happens to contain undefined. This code is meant to support a few cases, Module might be local or global, and defined or undefined. We want to avoid polluting the global scope, so we don't just do Module = ... if it's undefined.
First, the usual case is emscripten-generated code in the global scope. In this case, Module may or may not be defined, and may be local but still undefined, so we need to handle both.
Second, emscripten code may be just a module, like a game that uses ammo.js. In that case, the usage is
function Ammo(Module) {
// emscripten-generated code, uses the Module
return something;
}
so Module in this case is a function local, given as a param already defined for us.
We can't just declare var Module because that means Module is a local variable. So we need eval. For eval, we need a function that returns a value, because we need a try-catch. The try-catch uses Module, and will throw if Module is not a local (regardless of whether it contains undefined or not), which is exactly what we want.
It's possible this code could be simplified, though!

Categories

Resources