CommonJS module pattern - javascript

I have taken this from
Flux architecture
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var TodoConstants = require('../constants/TodoConstants');
var assign = require('object-assign');
var CHANGE_EVENT = 'change';
var _todos = {}; // collection of todo items
/**
* Create a TODO item.
* #param {string} text The content of the TODO
*/
function create(text) {
// Using the current timestamp in place of a real id.
var id = Date.now();
_todos[id] = {
id: id,
complete: false,
text: text
};
}
/**
* Delete a TODO item.
* #param {string} id
*/
function destroy(id) {
delete _todos[id];
}
var TodoStore = assign({}, EventEmitter.prototype, {
/**
* Get the entire collection of TODOs.
* #return {object}
*/
getAll: function() {
return _todos;
},
emitChange: function() {
this.emit(CHANGE_EVENT);
},
/**
* #param {function} callback
*/
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
/**
* #param {function} callback
*/
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
dispatcherIndex: AppDispatcher.register(function(payload) {
var action = payload.action;
var text;
switch(action.actionType) {
case TodoConstants.TODO_CREATE:
text = action.text.trim();
if (text !== '') {
create(text);
TodoStore.emitChange();
}
break;
case TodoConstants.TODO_DESTROY:
destroy(action.id);
TodoStore.emitChange();
break;
// add more cases for other actionTypes, like TODO_UPDATE, etc.
}
return true; // No errors. Needed by promise in Dispatcher.
})
});
where it says
There are a few important things to note in the above code. To start, we are maintaining a private data structure called _todos. This object contains all the individual to-do items. Because this variable lives outside the class, but within the closure of the module, it remains private — it cannot be directly changed from outside of the module. This helps us preserve a distinct input/output interface for the flow of data by making it impossible to update the store without using an action.
The bold part is unclear to me. How can js interpreter know that all those code is inside a module closure and not in the globals scope?
From where the module closure start and where ends?
As far as I know
The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global.
Any explanation?

You're actually missing the last line from the extract you quoted :
module.exports = TodoStore;
CommonJS is an API to define modules that use the following conventions :
Every file defines a module and is executed in an isolated environment ; that is to say that the variables it defines won't be available from outside the module.
To allow importing other modules, a global variable require is made available to the module, allowing it to import other modules
In the same way, the variable module is made available to the module so that it can set its exports attribute to define what should be exported by your module ; the value you set for module.exports in your module a.js is exactly what require('./a') will return.
Every JS environment that implements CommonJS has to know these rules. That includes Node.js, of course, but also bundlers like Browserify and Webpack that will package your codes so that these conventions are respected.
This way, you can control which part of your module will be exported.
P.S. : note that you can also use the exports var to define your exports, and that its use is slightly different from module.exports. See this StackOverflow question and answer for details

Common JS pattern uses the constructor function to define your utilities.
It is defined in the form of class.
var moduleName = function() {
// private variables
// public functions
this.method1 = function() {
// logic1 goes here
};
this.method2 = function() {
// logic2 goes here
};
};
So we are going to export the class to other modules using
module.exports = moduleName;
So that other modules can import it, instantiate it and then use the functionality.
How to use it?
var module = require('moduleName'); //importing the module created above
Here the module definition is fetched,executed and then available in 'module' variable.
This variable name can be anything
var objectOfModule = new module(); //instance is created
objectOfModule .method1(); //use1
console.log(objectOfModule .method2()); //use2
Thanks.

Related

Is it possible to inject global scope into instantiated class in ES6 aka singleton?

First of all I need to apologize because this is going to have alot of code in it, which will bloat this question. However I think this will help to understand my problem a little better.
Let's say I have this given MainModule:
'use strict';
/**
* Loads Module from given name.
* #class {LoadModules}
*/
class LoadModules {
constructor(moduleName) {
// define Modulename.
this.moduleName = moduleName;
}
/**
* Initialize module.
* #method init
* #return {void} [nothing]
*/
init() {
// Path Module.
const path = require('path');
// Require Module from given Name.
let ModuleToLoad = require(path.join(__dirname, 'Modules', this.moduleName, this.moduleName + '.js'));
// Instatiate Module.
ModuleToLoad = new ModuleToLoad();
// Start module.
ModuleToLoad.init();
}
}
And an other module which can be loaded into the MainModule:
/**
* This is a Module which can be loaded by the MainModule.
* #class {ModuleToBeLoaded}
*/
module.exports = class ModuleToBeLoaded {
constructor() {
/**
* Empty
*/
}
/**
* Initialize newly loaded Module.
* #method init
* #return {void} [nothing]
*/
init() {
console.log('module Loaded');
}
};
As you can see this is used to load modules dynamically, which works perfectly fine.
My problem is that my MainModule which loads other modules dynamically can't share its own global scope between the modules, or at least I didn't figure out how. I am well aware that this is complicated since my MainModule and ModuleToBeLoaded are in different files.
For example I have a LoggerClass in my global scope of my MainModule:
// This is in the global scope.
const LoggerClass = new Logger();
/**
* LoadModule class stuff comes after this.
*/
I want all Modules to access the LoggerClass as if it were in their own global scope without defining it again and again in each and every module. As an example I would change console.log in the ModuleToBeLoaded class into this:
/**
* Initialize newly loaded Module.
* #method init
* #return {void} [nothing]
*/
init() {
LoggerClass.log('module Loaded');
}
So basically I define Globals in the MainModule and I want to access these Globals in the Code of the ModuleToBeLoaded. A possible solution could be to change the constructor in the ModuleToBeLaoded. Like this:
constructor(LoggerClass) {
// Here I can set LoggerClass internally.
this.LoggerClass = LoggerClass;
}
/**
* Initialize newly loaded Module.
* #method init
* #return {void} [nothing]
*/
init() {
this.LoggerClass.log('module Loaded');
}
Which could allow me to instantiate the class like this:
// Instatiate Module.
ModuleToLoad = new ModuleToLoad(LoggerClass);
Is this the right way, or is there any other solution more preferably?
What I want to achieve is the known pattern singelton pattern in ES6.
For more information take a look at this Wikipage: https://en.wikipedia.org/wiki/Singleton_pattern
Sidenote: I'm in a NodeJS 7.10.0 environment without any 3rd party libraries.
Regards,
Megajin
LoggerClass.js this is how you make singletons (always same instance)
let instance;
module.exports = function () {
if (!instance) {
instance = new LoggerClass();
}
return instance;
}
class LoggerClass {
constructor() {
this.instanceData = Date.now();
}
log() {
console.log(`logging secret instance: ${this.instanceData}`);
}
}
LoadModules.js
const getLoggerClass = require('./LoggerClass');
module.exports = class LoadModules {
constructor(moduleName) {
this.moduleName = moduleName;
}
init() {
const path = require('path');
// changed the require statement, to make it simpler
let ModuleToLoad = require(path.join(__dirname, this.moduleName + '.js'));
ModuleToLoad = new ModuleToLoad(getLoggerClass());
ModuleToLoad.init();
}
}
ModuleToLoad.js
module.exports = class ModuleToBeLoaded {
constructor(logger) {
this.logger = logger;
}
init() {
console.log('ModuleToBeLoaded module Loaded');
this.logger.log();
}
};
ModuleToLoad2.js
module.exports = class ModuleToBeLoaded {
constructor(logger) {
this.logger = logger;
}
init() {
console.log('ModuleToBeLoaded2 module Loaded');
this.logger.log();
}
};
Demo
> node
> const LoadModules = require('./LoadModules');
> var load = new LoadModules('ModuleToLoad');
> var load2 = new LoadModules('ModuleToLoad2');
> load.init();
ModuleToBeLoaded module Loaded
logging secret instance: 1495528699144
> load2.init();
ModuleToBeLoaded2 module Loaded
logging secret instance: 1495528699144
As you can notice, the instance is the same, according to this.instanceData of LoggerClass
Removed comments to make code more minimal
I find it strange that you have a separate constructor and init. Why not do the initialization in the constructor?
Anyway, it seems like the right approach is indeed to pass your "global" to the constructor or init of the module you want to load.
If you really want it to be a global, you can add it to the global namespace.

Getting "TypeError: Dropdown is not a function" when trying to use a class in protractor

I'm getting "TypeError: Dropdown is not a function when trying to do the following:
/*
* Dropdown.js
*/
var __container;
function Dropdown(el) {
__container = el;
}
Dropdown.prototype = {
constructor: Dropdown,
getOptions: function() { return __container.element.all(by.css('option')); },
// my other prototype methods
}
--
/*
* PageObject.js
*/
var Dropdown = require('Dropdown');
var PageObject() {}
PageObject.prototype = {
constructor: PageObject,
myDd: new Dropdown(element(by.css('select')),
//my other prototype methods which do work
};
--
/*
* spec.js
*/
var PageObject = require('PageObject');
describe('Test my page', function() {
it('should test the dropdown', function() {
browser.get(mypage);
var pageObject = new PageObject();
expect(pageObject.myDd.getOptions().isPresent()).toBe(true);
});
});
as #11684 mentioned - you've forgot to export your Dropdown and PageObject classes and require('Dropdown'); returns undefined. Protractor is run on node.js so you need to fill the gaps about CommonJS modules. Also if you want to require modules which are not installed with npm you have to target them using relative paths so rather than
var PageObject = require('PageObject');
you'd need to do something like
var PageObject = require('./pages/PageObject');
var Dropdown = require('../helpers/Dropdown');
etc.
and to export a module in node environment using commonJS modules you need to either export them as set of properties/methods set on the exports object or you can assign your constructor directly to it so it's available directly on the required module
// in Dropdown
module.exports = Dropdown;
// in PageObject
module.exports = PageObject;
If you plan to use more of node.js in your testing you should read bit more about working with commonJS modules https://nodejs.org/docs/latest/api/modules.html and on node.js itself in general. Would recommend checking out what from ES6 you can use already http://node.green/ to make your tests more organised and readable as well

Requirejs dynamic reference to sub module methods?

Using requires, I’ve split larger class structures down into modules that use other modules within directory. There’s a main file that instantiates the other sub modules. This is an API class with two modules. One that deals with posting data to the endpoint, and the other that holds functions that are helpers to that post module:
define([
'./Post',
'./Helper'
], function (PostModule, HelperModule) {
'use strict';
var module = function () {
this.Post = new PostModule();
this.Helper = new HelperModule();
};
return module;
});
Now I can chain these modules like this:
var foo = new ApiModule();
foo.Post.postToAPI();
foo.Helper.matchAPIactionToEvent();
which is exactly what I want..
BUT, the problem is within the Post.js file, is that it doesn’t know anything about the Helper.js file. So I can’t take advantage of any of those methods. What I would like to do within the Post.js file is to be able to reference the other functions within the same class like so:
define([
'../environment',
'loglevel',
'../utility/Utility',
'jquery'
], function (EnvironmentModule, log, UtilityModule, $) {
'use strict';
var module = function () {
var environment,
utility,
api;
environment = new EnvironmentModule();
utility = new UtilityModule();
this.postToAPI = function (event, payload, callback) {
var apiEndpoint,
requestIdString,
eventAndAction;
apiEndpoint = environment.getEnvironmentPath().API;
requestIdString = utility.String.generateRandomString(32);
/*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/
eventAndAction = this.Helper.matchAPIactionToEvent(event);
/*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/
payload.event = eventAndAction.event;
payload.action = eventAndAction.action;
payload.requestID = requestIdString;
payload = $.param(payload);
$.post(apiEndpoint + '?' + payload, function (result) {
if (callback) {
callback(result);
}
});
return;
};
};
return module;
});
I figured out a working solution to the this, where I pass '../api/Helper' as one of the array values in the define statement of Post.js; but I don’t want to do that. What I want is to have Post.js be able to access any method from any other modules that are contained within the same directory. That way I don’t have to explicitly define them. It seems wrong to instantiate a new ApiModule() within Post.js. Here’s the directory structure:
Modules/api/Api.js
Modules/api/Post.js
Modules/api/Helper.js
...
I hope that makes sense. Is this possible?
Since you want any of the child modules to access any other child modules, what you could do is pass the parent module as an argument to the constructors of the child modules:
var module = function () {
this.Post = new PostModule(this);
this.Helper = new HelperModule(this);
};
Have the child modules store this information:
var module = function (parent) {
this.parent = parent;
Then use this this.parent to call the methods on other child modules:
eventAndAction = this.parent.Helper.matchAPIactionToEvent(event);
Note that if you would load '../api/Helper' with RequireJS in Post.js as you were thinking of doing, you would not be able to use the same object instance as the one defined on the parent module. You'd have to construct a new object for use in Post.js.

How to expand nodejs module

I would like to expand nodeJs module.
For example, I want to add a function into Utilities module.
like detect empty JSON object
function isEmptyObject(obj) {
return !Object.keys(obj).length;
}
So, I can use util.isEmptyObject() to detect empty JSON object.
Is it a good way to expand nodeJs module?
You can extend "utils" with defining your "UtilEx" module:
/* utils_ex.js */
var utils = require('utils');
utils.isEmptyObject = function() { };
exports = module.exports = utils;
/* end of utils_ex.js" */
/// client js
var utils = require('utils_ex');

Why was my javascript code not accepted at interview?

The interviewer told me that I have to follow javascript "patterns" and write "clean code". He also said that I should follow the prototype pattern. Here is my code sample:
//namespace declrations
var MyNamespace = {};
MyNamespace.UCs = {};
MyNamespace.Pages = {};
//function declarations
MyNamespace.UCs.test = function () { alert('this is a test function in user control namespace.'); }
MyNamespace.Pages.test = function () { alert('this is a test function in web page namespace.'); }
So can anybody point me to why this code is not ok? I mean, I have declared namespaces first and then added my members and functions like the above sample. So does it really have issues or am I missing something?
Well when you are writing code in a large environment, lots of problems can start happening. So it's important to separate your class definitions from how you use those classes. Which also means you have to make classes that can be unit tested to prove that they do what you say they do. Javascript is not a true object orientated language and as such there are several ways to "fake" it. But because the language has a lot of flexibility, we can duplicate some approaches.
One thing we want to stay away from is something called function scope simply because it can cause unintended "features" later down the road when 3 or 4 other programmers start making assumptions about what your code is doing. If they don't know a global variable was overwritten one or two function closures ago, it will make finding that problem more difficult. So I would suggest using a small class created by John Resig as it provides a very simple approach that gives you alot of the functionality you need.
So let's write some code.
var myNamespace = myNamespace || { }
/**
* Used to store a single entry in the log
*
* #class
*/
var myNamespace.LogEntry = Class.extend({
/**
* Used to track the beginning of the page load
*
* #private
* #static
*/
PAGE_LOAD_TIME = new Date().getTime(),
/**
* Used to store the current time
*
* #type int
*/
time : undefined,
/**
* The message of this log entry
*
* #type string
*/
msg : undefined,
/**
* #constructor
*
* #param {string} msg The message of this log entry
*/
init : function (msg) {
this.time = new Date().getTime() - this.PAGE_LOAD_TIME;
this.msg = msg
},
/**
* Displays this log entry in a single string
*
* #return {string} String representation of this log entry
*/
toString : function () {
return this.time + ": " + this.msg;
}
});
/**
* Used to store a log entry that has data associated with it.
*
* #class
* #extends myNamespace.LogEntry
*/
var myNamespace.DataEntry = myNamespace.LogEntry.extend({
/**
* Used to store data associated with this log entry
*
* #type object
*/
data : undefined,
/**
* #constructor
*
* #param {string} msg The message that describes this log entry
* #param {object} data The data associated with this entry
*/
init : function (msg, data) {
this._super(msg);
this.data = data;
},
/**
* #return {string} The string representation of this log entry
*/
toString : function () {
// Uses a JSON library to stringify the data into a json string.
return this._super() + JSON.stringify(this.data);
}
});
/**
* Provides an interface to log messages
*
* #class
*/
var myNamespace.Log = Class.extend({
/**
* Stores log entries
*
* #type myNamespace.LogEntry[]
*/
log : undefined,
/**
* #constructor
*/
init : function () {
this.log = [ ];
},
/**
* Logs a message into the log
*
* #param {string} msg The message you want to log
*/
msg : function (msg) {
this.log.push(new myNamespace.LogEntry(msg));
},
/**
* Log a message and data into the log
*
* #param {string} msg The message of this log entry
* #param {object} data The data associated with this log entry
*/
data : function(msg, data) {
this.log.push(new myNamespace.DataEntry(msg, data));
}
});
Ok, there is lots of stuff going on here. The main part is that this is all definitions of classes. I don't actually use anything up there. The program only stores the current time in LogEntry.PAGE_LOAD_START which is declared #static so the behavior will be expected. I've used lots of jsDocs here to make everything clear about what the intentions are. A program like intelliJ can use those to give your code feedback if you aren't using the classes the way you've documentated them.
This program will let you create and store log entries with possibly logging data. There are alot of other ways to do this. I declare everything before the constructor instead of inside the constructor so that I can document the types and whether they are private.
A programmer that has to use the log will know exactly how to use it and if they want to create or extend these classes, they can do so without unintended effects from function closure.
Here's how to use it:
var anotherNamespace = anotherNamespace || {};
var anotherNamespace = new myNamespace.Log();
...
anotherNamespace.log.msg("This is a test");
...
anotherNamespace.log.data("Test msg with data", data);
Of course the obvious thing missing here is a way to display all the data. But that could be in another class that iterates through the Log.log array and spits out the toString() into a web page or file. The point here is that the classes and their functions are simple, unit testable, and definition only.
FIrst of all, make use of object literals, all those assignments are a waste lines.
Second, you don't have the prototype "pattern" implemented anywhere, also I'd go for some encapsulation if you have full control over the namespaces:
(function() { // anonymous wrapper
function Foo(a) { // i can haz prototype "Pattern"
this.memberVal = a;
}
Foo.prototype = {
someMethod: function(value) {
console.log(value, this.memberVal);
},
yam: function() {
}
};
// Let's assume we have full control here, otherwise Alnitak's answer is fine too.
window.namespace = {
test: {
Foo: Foo
}
};
})();
var test = new namespace.test.Foo(123);
test.someMethod('bla');
Maybe the interviewer literally meant you should be using the 'namespace' method?
Tutorial with example of usage:
http://elegantcode.com/2011/01/26/basic-javascript-part-8-namespaces/
Your code looks (mostly) fine, if the intent was to just put utility functions in a shared namespace, without any object orientation or data encapsulation.
I would have made one change, on the initial name space declarations:
var MyNamespace = MyNamespace || {};
MyNamespace.UCs = MyNamespace.UCs || {};
MyNamespace.Pages = Mynamespace.Pages || {};
to ensure that the code didn't obliterate any existing methods in those namespaces.

Categories