Explanation of define of the RequireJS library - javascript

I started to read several tutorials about RequireJS. In none of them was the "define" keyword explained satisfactorily for me. Could someone help me with the following :
define(
["Models/Person", "Utils/random", "jquery"],
function (Person, randomUtility, $) {..}
)
What is "define"? Is define a function with an array and an anonymous function inside of it? Or is it something else? Can someone give me more information about this kind of definitions?
Addition: Thank you nnnnnn and pradeek for your answers. Here in Europe it was 2:30 in the night when I was posting the question. Maybe therefore I didn't recognize it was a simple function call.

define is not specific to RequireJS, it is part of the AMD specification. Burke will note that RequireJS doesn't implement exactly how AMD specifies it, since AMD didn't really keep browsers in mind.
define doesn't have an anonymous function in it. define is a method made available to AMD based JavaScript files for loading their data. Libraries like RequireJS make this available to you. The specific implementation probably isn't valuable to you. So I'll go over the one you provided as it's the most common way to declare a module.
define( [array], object );
Array is a list of modules that this module depends on. There is a 1 to 1 relationship between modules and files. You can not have multiple modules in a file nor multiple files for one module.
Object is the module you are defining. This can be anything, a struct, or a function that returns a struct. Read the docs on RequireJS for more details.
If object is a function, the arguments passed to the function are the modules listed as dependencies in the first define argument. It is also important to note than when you pass a function as object, it will only run one time. The methods or properties created on this one instantiation can be accessed at any time though, can then be accessed by other modules that list this module as a dependency.
Good luck, I recommend playing around with this and reading the docs when things don't make sense. RequireJS docs are great as a quick start on how AMD modules work.

I found define defined near the bottom of require.js (I too was wondering what kind of a thing this define word is, and this is the answer I was looking for):
/**
* The function that handles definitions of modules. Differs from
* require() in that a string for the module should be the first argument,
* and the function to execute after dependencies are loaded should
* return a value to define the module corresponding to the first argument's
* name.
*/
define = function (name, deps, callback) {
var node, context;
//Allow for anonymous modules
if (typeof name !== 'string') {
//Adjust args appropriately
callback = deps;
deps = name;
name = null;
}
//This module may not have dependencies
if (!isArray(deps)) {
callback = deps;
deps = null;
}
//If no name, and callback is a function, then figure out if it a
//CommonJS thing with dependencies.
if (!deps && isFunction(callback)) {
deps = [];
//Remove comments from the callback string,
//look for require calls, and pull them into the dependencies,
//but only if there are function args.
if (callback.length) {
callback
.toString()
.replace(commentRegExp, '')
.replace(cjsRequireRegExp, function (match, dep) {
deps.push(dep);
});
//May be a CommonJS thing even without require calls, but still
//could use exports, and module. Avoid doing exports and module
//work though if it just needs require.
//REQUIRES the function to expect the CommonJS variables in the
//order listed below.
deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
}
}
//If in IE 6-8 and hit an anonymous define() call, do the interactive
//work.
if (useInteractive) {
node = currentlyAddingScript || getInteractiveScript();
if (node) {
if (!name) {
name = node.getAttribute('data-requiremodule');
}
context = contexts[node.getAttribute('data-requirecontext')];
}
}
//Always save off evaluating the def call until the script onload handler.
//This allows multiple modules to be in a file without prematurely
//tracing dependencies, and allows for anonymous module support,
//where the module name is not known until the script onload event
//occurs. If no context, use the global queue, and get it processed
//in the onscript load callback.
(context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
};

I found this page Why AMD? very helpful. To summarize from this page, AMD specification is helpful in overcoming "write a bunch of script tags with implicit dependencies that you have to manually order" problem. It is helpful in loading the dependencies before executing the required functions, similar to import in other programming languages like python. AMD also prevents the global namespace pollution problem. Check "It is an improvement over the web's current "globals and script tags" because" section.

I think the RequireJs API specification sums it up pretty well:
If the module has dependencies, the first argument should be an array of dependency names, and the second argument should be a definition function. The function will be called to define the module once all dependencies have loaded. The function should return an object that defines the module.
They list examples of all the various syntactic forms of defines.

Related

Hide globals in Flow?

I am writing some code in JavaScript + Flow and would like to keep it as pure as possible, which also means skipping globals such as window or document, passing those as function arguments. But itโ€™s quite easy to forget a stray document reference here or there. Is it possible to ban those globals somehow, allowing them only in the top-level file? So far I am doing this at the top of most of my documents:
const window = undefined
const document = undefined
This way only instances passed in as arguments work:
// This works
function foo(document: Document) {
document.doThisOrThat();
}
// This triggers a typecheck error ๐ŸŽ‰
function bar() {
document.doThisOrThat();
}
Are there other solutions? (I would love a whitelist approach, disallowing all globals except those whitelisted.)
You can set Flow to ignore the flowlibs by adding no_flowlib=true in the [options] section of the flowconfig.
From there, you can make your own libs folder and only include the library definitions you want. To make them globally available, add the path to your libs folder in the [libs] section of your flowconfig.

how does requirejs know to load a required js file before I ever mention the file name?

I am looking #Domenic's simple example of using requirejs, from this answer:
simple example for using require.js
which I am including here.
shirt.js:
define({
color: "black",
size : "large"
});
logger.js:
define(function (require) {
var shirt = require("./shirt");
return {
logTheShirt: function () {
console.log("color: " + shirt.color + ", size: " + shirt.size);
}
};
});
main.js:
define(function (require) {
var shirt = require("./shirt");
var logger = require("./logger");
alert("Shirt color is: " + shirt.color);
logger.logTheShirt();
});
main.html:
<script data-main="../js/main" src="../js/require.js"></script>
There's something very strange going on:
at the point where shirt.color is used in main.js,
shirt.js and logger.js have just been scheduled to be loaded, asynchonously (I presume),
so shirt.js hasn't actually been read yet. The reason I presume the loading is asynchronous is that my impression is that synchronous loading has been pretty much outlawed in javascript in chrome (XMLHttpRequest still has an option to be synchronous, but if used, it warns on the chrome console Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.).
And yet, this little app seems to work, reliably.
It even works reliably if I replace "./shirt.js" by a url referring to a resource on the other
side of the world, and I clear my browser cache before loading the html page.
How can this be??
If I look at timings in chrome dev console, it appears that the time-consuming shirt.js load
actually happened before the function that requested it even started.
I.e. somehow it knew to load shirt.js before anything in the program referred to "./shirt" at all.
It seems there is some very sneaky magic going on here.
So I'm interested to know:
how did requirejs know to load shirt.js before anything asked for it?
to what extent can this be relied on?
how would one modify this example to avoid relying on the sneaky magic?
for those of us who don't trust sneaky magic, is there a way to disable it when using requirejs?
how did requirejs know to load shirt.js before anything asked for it?
This is your module:
define(function (require) {
var shirt = require("./shirt");
var logger = require("./logger");
alert("Shirt color is: " + shirt.color);
logger.logTheShirt();
});
When define is called, RequireJS detects that it was called without a dependency list. So it scans the callback you pass for instances of the require call taking a single argument which is a string literal, and it grabs the single argument and makes a list of these arguments that it takes as the dependency list of the module. Your module becomes functionally equivalent to this:
define(["require", "./shirt", "./logger"], function (require) {
var shirt = require("./shirt");
var logger = require("./logger");
alert("Shirt color is: " + shirt.color);
logger.logTheShirt();
});
So ./shirt and ./logger are loaded before the callback is actually called. Then when require("./shirt") and require("./logger") are executed, they are just lookups in a map of already loaded modules. (And, because of this, calls to require with a single string argument can only work when called in a callback passed to define. Otherwise, you get the dreaded "Module has not been loaded yet for context" error.)
This capability is called the "CommonJS sugar" because a require call that uses a single parameter which is a string and returns a module is what CommonJS supports natively. The native AMD require call takes an array of dependencies as the first argument and an optional callback to which the resolved modules are passed.
to what extent can this be relied on?
I've relied on the CommonJS sugar for hundred of modules without problem.
The one limitation to this pattern is if you try to pass something else than a string literal to require. For instance if you do this:
define(function (require) {
var shirtName = "./shirt";
var shirt = require(shirtName);
This will throw off RequireJS. It won't detect that your module needs the ./shirt module and you'll get the error I mentioned above.
how would one modify this example to avoid relying on the sneaky magic?
define(["./shirt", "./logger"], function (shirt, logger) {
alert("Shirt color is: " + shirt.color);
logger.logTheShirt();
});
for those of us who don't trust sneaky magic, is there a way to disable it when using requirejs?
There's no flag you can use to prevent RequireJS from supporting the CommonJS sugar. If you want to avoid relying on it in your own code, you can code your modules like I've shown in the previous snippet: call define with a list of dependencies as the first argument, and get the modules as arguments of your callback.
This being said, I see no good reason to do that. I've used RequireJS for years and if anything I've been moving code that uses define with a list of dependencies to code that relies on the CommonJS sugar. I find that the latter works better with various development tools.

How to parse and load javascript object?

I have one js files . I load it using other javascrupt file using eval() function. I have seen eval is slow and with some other limtation. Since i need to store my JS file object in cache and use it anytime i need after apllication starts. I dont want to do eval() everytime.
Is there anyway to do it in simple way.
var evalObj;
if(evalObj) {
console.log('eval object already evaluated');
_myfunctionInJSFile_(layouts.FormatDate(startTime), threadName, level, categoryName, message);
}
else {
evalObj = eval(fs.readFileSync('./myJSFile', 'utf8'));
console.log('re evaluating object ..' );
_myfunctionInJSFile_(layouts.FormatDate(startTime), threadName, level,message);
}
myJSFile
var _sigmaAlarmHandler_ =function(args)
{
var args = Array.prototype.slice.call(arguments);
args.unshift();
console.log('Alarm : ', args);
}
Either the conditional eval is not working.
In node.js you can simple require your js-file:
var obj = require('./myJSFile');
obj.foo();
./myJSFile.js:
exports.foo = function() {
console.log('foo');
}
This file becomes a module with exported functions, that you need.
It loads once, then every require reuse already loaded module.
If it is not commonjs-compliant (i.e. using module.exports will not work), then you can run it in its own vm:
var vm = require('vm');
vm.runInNewContext(jscode,{/*globalvars*/});
where the second parameter is an object with global vars made available in the context in which the jscode is run. So if the second param is, say, {a:1,b:"foo"} then your jscode will run with the global variable a set to 1 and the global variable b set to "foo".
The jscode itself is a string that you load from a file or elsewhere.
Think of vm.runInNewContext() as "practice safe eval". Well, relatively safe, you can still do some dangerous stuff if you pass in particular vars, like process or file etc.
I used this for the declarative part of cansecurity http://github.com/deitch/cansecurity for nodejs
You can view the sample in the file lib/declarative.js
Here is the API for vm http://nodejs.org/api/vm.html
There are options to run in the same context, etc. But that is very risky.
When you actually run the code, using your example above:
_myfunctionInJSFile_(layouts.FormatDate(startTime), threadName, level,message);
you are looking to pass in 4 params: startTime, threadName, level, message and execute the function. The issue is that you cannot run the function on the current context. You need the function to be defined and run in the file. So you should have something like:
vm.runInNewContext(jscode,{startTime:layouts.FormatDate(startTime),threadName:threadName,level:level,message:message});
And then the jscode should look like
function _myfunctionInJSFile(startTime,threadName,level,message) {
// do whatever you need to do
}
// EXECUTE IT - the above vars are set by the global context provide in vm.runInNewContext
_myfunctionInJSFile(startTime,threadName,level,message);
If you prefer to define the function and have it loaded and run in this context, then just use the commonjs format.
I think i have found the answer for this.
Since my application is running in node js which uses v8 engine platform. When the application starts v8 engine caches all the code/configuration and can be used anytime.
Similarly in my code i will pre-load the JS code using eval and i will do it only once. So on next call i will return only the loaded JS code. Here i need to modify the code to load once.
But main point we have look is that in future if any body has similar requirement they can cache their JS codes using eval (thanks to v8 engine) and use it till your application is running.

Tell the Closure Compiler not to rename any function

I want to compile part of my JS code which is based on Mootools library.
I want all the variables be renamed but none of the function, the called and defined ones. Because most of the called one are from mootools and those defined are called from outside:
code to be compiled:
// textnum is safe to be renamed, all variables are
textnum = 0;
// loadText can't be ranmed because is called from outside
function loadText()
{
textnum++;
document.body.setStyle("font", "12px");
// here setSyle can't be renamed
}
Is there a way to tell it to rename only vars?
I found out this is an open source project, Is there a way to manipulate it somehow that it doesn't touch function at all!?
Put the code to be compiled in a namespace or anonymous function wrapper and use simple optimizations. This renames all internal vars and functions but not global ones such as setStyle.
Functions which should not be renamed are defined in the global scope. This is not as much of a pain compared to defining externs and exports.

How to structure my javascript/jquery code?

I am toying around with a pretty intensive ajax based jquery web application. It is getting to a point where I almost loose track of what events that should trigger what actions etc.
I am sort of left with a feeling that my javascript structure is wrong, on a more basic level. How do you guys structure your javascript/jquery code, the event handling etc., any advise for a newbie javascript developer.
AMDS!
It's been awhile since first answers got posted to this question and many things have changed.
First and foremost, the JS browser world seems to be moving towards AMDs (asynchronous module definition) for code organization.
The way that works is you write ALL your code as AMD modules, e.g.:
define('moduleName', ['dependency1', 'dependency2'], function (dependency1, dependency2) {
/*This function will get triggered only after all dependency modules loaded*/
var module = {/*whatever module object, can be any JS variable here really*/};
return module;
});
And then modules get loaded using AMD loaders like curl.js or require.js etc, for example:
curl(
[
'myApp/moduleA',
'myApp/moduleB'
],
).then(
function success (A, B) {
// load myApp here!
},
function failure (ex) {
alert('myApp didn't load. reason: ' + ex.message);
}
);
Advantages are:
You only have to include single <script> element on your page that loads AMD loader itself (some of them are quite tiny).
After that all JS files will be fetched automatically in asynchronous NON BLOCKING! fashion, thus way faster!
Necessary modules will get executed only after its dependencies got loaded.
Modular (which means code that is easier to maintain and re-use).
Global variables pollution can be completely curbed if used correctly.
Honestly, once concept has clicked in your head, you'll never go back to your old ways.
P.S: jQuery does register itself as AMD module starting from version 1.7.
More information on AMDS:
https://github.com/cujojs/curl
http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition
http://requirejs.org/
http://www.bennadel.com/blog/2275-Using-RequireJS-For-Asynchronous-Script-Loading-And-JavaScript-Dependency-Management.htm
https://github.com/Integralist/Blog-Posts/blob/master/2012-01-04-Beginners-guide-to-AMD-and-RequireJS.md
For javascript code I found the following links from Christian Heilmann indispensable
The module pattern
Configuring scripts
I also really like the method described by Peter Michaux here
For jQuery, I heartily recommend reading the guides on Authoring and I found this tutorial on jQuery plugin patterns very good
To keep my events in control I use a publish/subscribe mechanism
jQuery.subscribe = function( eventName, obj, method ){
$(window).bind( eventName, function() {
obj[method].apply( obj, Array.prototype.slice.call( arguments, 1 ) );
});
return jQuery;
}
jQuery.publish = function(eventName){
$( window ).trigger( eventName, Array.prototype.slice.call( arguments, 1 ) );
return jQuery;
}
Here's an example of its use
// a couple of objects to work with
var myObj = {
method1: function( arg ) {
alert( 'myObj::method1 says: '+arg );
},
method2: function( arg1, arg2 ) {
alert( arg1 );
//republish
$.publish( 'anEventNameIMadeUp', arg2 );
}
}
var myOtherObj = {
say: function(arg){
alert('myOtherObj::say says: ' + arg);
}
}
// you can then have all your event connections in one place
//myObj::method2 is now listening for the 'start' event
$.subscribe( 'start', myObj, 'method2' );
//myOtherObj::say is now listening for the 'another' event
$.subscribe( 'anotherEvent', myOtherObj, 'say' );
//myObj::method1 is now listening for the 'anEventNameIMadeUp' event
$.subscribe( 'anEventNameIMadeUp', myObj, 'method1' );
//so is myOtherObj::say
$.subscribe( 'anEventNameIMadeUp', myOtherObj, 'say' );
// ok, trigger some events (this could happen anywhere)
$.publish( 'start', 'message1', 'message2' );
$.publish( 'anotherEvent', 'another message' );
I definitely recommend reading up on the object literal pattern in addition to the module pattern; here's a good writeup:
http://ajaxian.com/archives/show-love-to-the-object-literal
(function($, window, slice)
{
$.subscribe = function(eventName, obj, method)
{
$(window).bind(eventName, function()
{
obj[method].apply(obj, slice.call(arguments, 1));
});
return $;
};
$.publish = function(eventName)
{
$(window).trigger(eventName, slice.call(arguments, 1));
return jQuery;
};
})(jQuery, window, Array.prototype.slice);
To add to the existing answers, here's a great post that covers more advanced techniques that build on the Module Pattern.
Once your Javascript code reaches a certain size, you'll inevitably want to refactor it by breaking it into multiple files / modules / sub-modules. If you're not sure how to accomplish this using the module pattern, this article is a must-read.
My js files usually follow a naming convention similar to this :
xxx.utility.js
mypage.events.js
xxx.common.js
/lib/
/OS-DoNotDistribute/lib/
Where
'mypage' is the name of the html,
aspx, php, etc file.
'xxx' is the concept. (i.e. orders.common.js)
'utility' signifies it's a reusable
library script (i.e. ajax.utility.js, controlfader.utility.js)
'common' is reusable functionality
for this app, but not reusable across
other projects
'lib' is a subdirectory for any external or library scripts
'OS-DoNotDistribute' is a subdirectory to ensure no OS licensed code is distributed if the app is ever sold.
Also, for ajax, I have a special naming convention for call back functions, so it's easy to tell what they are.
I'm not sure it that's close to what you were looking for, but I hope it helps.
I really like these articles:
http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html
http://stefangabos.ro/jquery/jquery-plugin-boilerplate-revisited/
They helped me to understand how telerik creates extensions for asp.net mvc.
I like the idea of AMDs (see nix's answer).
But I typically compile all my JS files into one JS file.
In that case the asynchronous part is not needed. So I wrote a little "Infile Module Loader".
Here it is: https://codereview.stackexchange.com/questions/14530/a-little-infile-amd
We can use mvc pattern in our javascript-jquery applications.
(Backbone.js, knockout.js vs.... ) are mature libraries we can use for this aim.

Categories