JS Require Guide

Overview

The JS require and include implementation permits including additional Javascript files as added functionality for any js or jsui objects. This permits building reusable code which can be used in a number of Javascript objects as well as code organization in separate files to help make code more manageable and maintainable. The require implementation is similar to Common JS 1.0 modules, as used by node.js and other systems, and the include implementation allows code to exist within global script scope similar to how html files may add script elements to the main page's document model. For more information on Common JS, please see http://wiki.commonjs.org/wiki/CommonJS

Require Usage

For require, the module must be defined by assigning anything the module wishes to export as properties of an "exports" property. This exports property is the return value from the require() function. Modules included using require are always scoped to prevent collisions in the top level script. Currently we don’t support any of the other typcial node.js module gobal properties like module.id, module.loaded, etc. For example, the following code may be placed in a file named "require-example.js" in the Max search path and be used by another Javascript file:


exports.foo = 37;
exports.bar = function () {
	post("I’m executing bar\n");
}

The above code may then be included and used in another js file as the following:


var reqmodule = require("require-example");
reqmodule.bar();
post("foo is "+reqmodule.foo+"\n");

Include Usage

To include Javascript at the top level, rather than encapsulated inside a module, you may call include(filename) which simply includes the javascript within the calling javascript file. This is more dangerous practice than the encapsulated module definition of CommonJS and require(), as it includes them within the variable scope of the calling Javascript file and thus does not prevent the collision of variables. However, this may be useful in a variety of situations where that is desirable. Additionally, a Javascript object may be passed in as a second argument to the include() function, and the referenced javascript file will add any properties and methods to the object passed in rather than the top level object. This is another way to limit scope. For example, the following code may be placed in a file named "include-example.js" and be referenced by another Javascript file, and any variables will be resolved within the calling Javascript file, or optionally within the object scope of an object passed in as a second argument:


function included_function()
{
	post("I'm an included function\n");
	post("someval tells me \""+someval+"\"\n");
}

And the following calling Javascript file will demonstrate the differences in variable scope as handled by require and include respectively:


var reqmodule = require("require-example"); 
reqmodule.bar();
post("foo is "+reqmodule.foo+"\n");

post("-------------------------------------[1]\n");

include("include-example"); 
var someval = "I'm dangerously top level";
included_function();

post("-------------------------------------[2]\n");

var scopeob = new Object();
scopeob.someval = "I'm a scopy scopebot";
include("include-example", scopeob); 
scopeob.included_function();

post("-------------------------------------[3]\n");

This example will print out the following in the Max console. Note that the variable "someval" used within include-demo.js will resolve first in the topmost variable scope to "I'm dangerously top level", and in the example with an object passed in as a second argument to the include() function, within the scope of that object to the property value "I'm a scopy scopebot":


js: I'm executing bar
js: foo is 37
js: -------------------------------------[1]
js: I'm an included function
js: someval tells me "I'm dangerously top level"
js: -------------------------------------[2]
I'm an included function
someval tells me "I'm a scopy scopebot"
js: -------------------------------------[3]