HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Simple JavaScript Module "Loader"

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javascriptloadersimplemodule

Problem

I have written a simple JS module "loader" (loader is in quotes because it doesn't actually load the files) that is designed to resolve simple dependencies between modules. It is heavily inspired by module.js and takes some of it's design from it.

Here is the code itself:

`(function() {
function create() {
var definitions = {},
instances = {};

// Returns whether or not a module with the provided id is defined.
var defined = function(id) {
return definitions.hasOwnProperty(id);
};

// Define a module with the provided id and definition.
var define = function(id, definition) {
if(defined(id)) {
throw new Error('module already defined: ' + id);
}

definitions[id] = definition;
};

// Undefine a module with the provided id.
var undefine = function(id) {
if (!defined(id)) {
throw new Error('module not defined: ' + id);
}

delete definitions[id];
delete instances[id];
};

// Require a module with the provided id.
var require = function(id) {
var stack = [];

var internalRequire = function(id) {
if(!defined(id)) {
throw new Error('module not defined: ' + id);
}

// If we have already seen this id on the require stack, we've got
// some form of cyclic dependency.
if (stack.indexOf(id) !== -1 && stack.push(id)) {
throw new Error('cyclic dependency: ' + stack.join(' -> '));
} else {
stack.push(id);
}

// If we already have an instance for this module, return it.
if (instances.hasOwnProperty(id)) {
return instances[id];
} else if (typeof(definitions[id]) === 'function') {
// Otherwise if our definition is a function, call it and pass the
// require method to it.
return instances[id] = definitions[id].call(null, internalRequire);
} else {
// Otherwise just return the definition

Solution

The names define and defined are too similar, which could lead to mistakes. I suggest renaming the latter to isDefined.

You could flatten some of the conditionals when all branches leave the block. For example:

// If we have already seen this id on the require stack, we've got
// some form of cyclic dependency.
if (stack.indexOf(id) !== -1 && stack.push(id)) {
  throw new Error('cyclic dependency: ' + stack.join(' -> '));
}
stack.push(id);

// If we already have an instance for this module, return it.
if (instances.hasOwnProperty(id)) {
  return instances[id];
}

if (typeof(definitions[id]) === 'function') {
  // Otherwise if our definition is a function, call it and pass the
  // require method to it.
  return instances[id] = definitions[id].call(null, internalRequire);
}

// Otherwise just return the definition itself (useful for objects
// e.g. constants).
return instances[id] = definitions[id];

Code Snippets

// If we have already seen this id on the require stack, we've got
// some form of cyclic dependency.
if (stack.indexOf(id) !== -1 && stack.push(id)) {
  throw new Error('cyclic dependency: ' + stack.join(' -> '));
}
stack.push(id);

// If we already have an instance for this module, return it.
if (instances.hasOwnProperty(id)) {
  return instances[id];
}

if (typeof(definitions[id]) === 'function') {
  // Otherwise if our definition is a function, call it and pass the
  // require method to it.
  return instances[id] = definitions[id].call(null, internalRequire);
}

// Otherwise just return the definition itself (useful for objects
// e.g. constants).
return instances[id] = definitions[id];

Context

StackExchange Code Review Q#129530, answer score: 2

Revisions (0)

No revisions yet.