Structuring a NodeJS module - variables and methods - javascript

I want to create modules to structure my NodeJS application, but I'm a little lost, and I haven't found anything (with hours of searching) that is completely definitive on the subject.
Say I'd like to create a "user" module, from which I can create new users in my code using something like:
var newUser = new User();
Ideally, I'd require my module at the top of my code using something like:
var User = require('../lib/user');
This works great. The question is, how should I structure the user module? Is the following the best way?
module.exports = function User() {
var authorized = false;
var username = undefined;
var password = undefined;
var statistics = undefined;
this.authorized = function() {
return authorized;
}
this.username = function() {
return username;
}
this.statistics = function() {
return statistics;
}
}
I'm writing getters and setters for my various module variables, allowing me to hide things I don't want to accidentally access from other code. However, I have done it this way before:
function User() {
this.authStatus = false;
this.email;
this.displayName;
this.inSession;
}
User.prototype.isAuthenticated = function() {
return(this.authStatus && this.email && this.displayName)
}
User.prototype.isInSession = function() {
return(this.inSession && this.isAuthenticated());
}
exports.User = User;
This works too, with one caveat; I haven't found a way to access the user properties from within closures. If my understanding is correct, with the second implementation, I can't. This means if I need to hand a function off to a db library as a callback to edit the user's properties, I can't. That'd look something like:
User.prototype.login = function() {
db.doDbStuff('get user data query', function(_error, _result) {
this.username = _result[0].name; //this code will not work
});
}
The code doesn't work, to my understanding, because the "this" keyword is within the scope of the closure, not the User. Even if the code were to be placed within the User function:
function User() {
this.login = function() { //you know
It wouldn't work.
I guess my question is, what's the best solution to this problem? Is it the method I presented in the first code block? That seems rather cumbersome and messy and prone to variable collision. I'm scared.
Thanks in advance!

I typically go with the second approach, attaching functions to the prototypes.
The issue you're having with variables "not being available in closures" has nothing to do with prototypes. You'd have that same issue either way you structure it.
It's to do with javascript's oft-confusing dynamic this:
http://robotlolita.me/2011/10/09/understanding-javascript-oop.html#sec-2-1
Basically, you need to do something like:
User.prototype.login = function() {
var self = this // bind this to self so you have a reference to what `this` was
db.doDbStuff('get user data query', function(_error, _result) {
self.username = _result[0].name; // self refers to the original `this`, so this works.
});
}
You also have the option of using function.bind: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Within the bound function, the value of this will be whatever value you provided to .bind(value):
User.prototype.login = function() {
db.doDbStuff('get user data query', (function(_error, _result) {
this.username = _result[0].name; // bind fixes the original `this`, so this also works.
}).bind(this));
}
Whether you use function.bind or self = this is somewhat of a personal taste question, but we were doing some benchmarks in the freenode#nodejs the other day and discovered bind() is 20 something times slower than var self = this.
As to your original question about how to structure modules, there are so many examples to learn from on github. Simply find your favourite module and inspect how they structure it. I notice that many people seem to prefer factories over exposing constructors directly (e.g. require('module').create() ). Your call.

As a different approach, I am a fan of the following pattern.
module.exports = function User(data) {
//this properly private stuff.
var privateVar;
var username = data.username;
var pass = data.pass; //etc
function privateFunc() {
}
return {
login: function(cb) {
db.doStuff(username, pass, cb);
}
};
};

User.prototype.login = function() {
var _this = this;
db.doDbStuff('get user data query', function(_error, _result) {
_this.username = _result[0].name; //this code will now work
});
}
The 'this' you used was outside its scope, it was the callback 'this'.

Related

Are private members in javascript really that complicated?

I am trying to clarify my understanding of private members in Javascript. It seems like it should be easy:
function MyClass(param) {
var thisIsPrivate = param;
this.getPrivateMember = function() {
return thisIsPrivate;
}
}
var thing = new MyClass('tada!');
console.log(thing.thisIsPrivate) // undefined
console.log(thing.getPrivateMember()) // "tada!"
In my reading, I keep coming across articles that don't even mention this as an option, but rather come up with complicated solutions like using closures or WeakMaps. Often the conclusion is that there is no good way to work with private members in Javascript.
Can anybody fill me in on what I'm missing? Is this a bad idea for some reason?
Thanks for the replies. So my understanding of the limitation of this approach is that methods added outside of the constructor cannot see the 'private' variables. I feel somewhat enlightened.
function MyClass(param) {
var thisIsPrivate = param;
this.getPrivateMember = function() {
return thisIsPrivate;
}
}
MyClass.prototype.showPrivateMember = function(){
console.log(thisIsPrivate);
}
var thing = new MyClass('tada!');
console.log(thing.thisIsPrivate) // undefined
console.log(thing.getPrivateMember()) // tada!
thing.showPrivateMember(); // ReferenceError: thisIsPrivate is not defined at MyClass.showPrivateMember
thing.showPrivateMember = function(){
console.log(thisIsPrivate);
}
thing.showPrivateMember(); // ReferenceError: thisIsPrivate is not defined at MyClass.showPrivateMember

Why we use public and private variable separately

var Command = function () {
var _self = this,
//flag to indicate that the operation is running
_isRunning = ko.observable(false),
//property to save the error message
_errorMessage = ko.observable();
//public properties
this.isRunning = _isRunning;
this.errorMessage = _errorMessage;
};
Why does this example use both private and public variables? Is this a design pattern we are following?
In just the code you've quoted, there's no reason. But my guess is that later in that outermost function, you have something like this:
this.doSomething = function() {
if (_isRunning()) {
// do one thing
} else {
// do something else
}
};
The reason for having the local variables is so that it doesn't matter what this value the function is called with.
That said, the _self variable already solves that problem for you just as well, making the _isRunning and _errorMessage variables purely convenience aliases. The above could just as well be:
this.doSomething = function() {
if (_self.isRunning()) {
// do one thing
} else {
// do something else
}
};
There's no particular design pattern here, it's just using the fact that functions created within other functions are closures over the local variables (and a few other things) of the function they're created in.

Is it possible to access other module export functions within the same file?

I have two functions in the same file, both accessed externally. One of the functions is called by the second.
module.exports.functionOne = function(param) {
console.log('hello'+param);
};
module.exports.functionTwo = function() {
var name = 'Foo';
functionOne(name);
};
When this gets executed, the call to functionOne is flagged as not defined.
What's the right way to reference it?
One pattern I've found to work is by referencing the file itself.
var me = require('./thisfile.js');
me.functionOne(name);
... but it feels like there has to be a better way.
Just simply module.exports.functionOne().
If that's too cumbersome, just do the following:
function fnOne() {
console.log("One!");
}
module.exports.fnOne = fnOne;
var me = require(module.filename);
me.functionOne(name);
or just use exports object itself
module.exports.functionOne(name);
I guess I've been thinking of require is an equivalent of include, import, etc. If there is another way around it, it might be interesting to see it. I'm still wet behind the ears with node.
James Herdmans Understanding Node.js "require" post really helped me when it came to helping with code organization. Its definitely worth a look!
// ./models/customer.js
Customer = function(name) {
var self = this;
self.name = name;
};
// ./controllers/customercontroller.js
require("../models/customer");
CustomerController = function() {
var self = this;
var _customers = [
new Customer("Sid"),
new Customer("Nancy")
];
self.get() {
return _customers;
}
};

javascript organisation

I came across this Q/A on javascript code organisation.
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
Currently I do this,
var DED = new Object;
DED = {
sidebar : {
method_1 : function (data){
//some stuff
},
method_2 : function(data){
//do more
}
},
main : {
//.......
},
globalVariables : {
//...
}
}
What is the advantage of one over the other?
Warning: newbie here.
As indicated, that method uses closures to implement private functions and data. It's an alternative to the constructor method (below). E.g.
var DED = new (function()
{
var private_var;
function private_method()
{
// do stuff here
}
this.method_1 = function()
{
// do stuff here
};
this.method_2 = function()
{
// do stuff here
};
})();
With the DED method shown in your question, there is no constructor. Rather the function returns an object created from an object literal. The functions in that object have the private variable and method closed into them.
What you return from the anonymous self-calling function (function(){})() is the interface you publish for your "module" (DED).
DED.method_1() is public. private_method/private_var are not accessible from outside but everything inside of your self-calling function has access to them.
If you like this kind of access-control this is a good way to prevent other developer from accidentally messing with the internals of your module. In a lot of cases i'd just go for a naming convention like a leading underscore to indicate internals.
Javascript is very dynamic and if someone really wants to mess with code they have no write-access to they will be able to do so. Edit: This turns out to be a wrong assuption and not the case for private data in constructors or closures. Please, see: http://www.crockford.com/javascript/private.html

Object Creation in javascript

Just for the kicks i am trying to create a simple data object in javascript. Here is the code.
var roverObject = function(){
var newRover = {};
var name;
var xCord;
var ycord;
var direction;
newRover.setName = function(newName) {
name = newName;
};
newRover.getName = function() {
return name;
};
newRover.setDirection = function(newDirection) {
direction = newDirection;
};
newRover.getDirection = function() {
return direction;
};
newRover.setXCord = function(newXCord) {
xCord = newXCord;
};
newRover.getXCord = function() {
return xCord;
};
newRover.setYCord = function(newYCord) {
yCord = newYCord;
};
newRover.getYCord = function() {
return yCord;
};
newRover.where = function(){
return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
};
return newRover;
};
rover1 = new roverObject();
rover2 = new roverObject();
rover1.setName("Mars Rover");
rover1.setDirection("NORTH");
rover1.setXCord(2);
rover1.setYCord(2);
console.log(rover1.where());
console.log(rover1);
rover2.setName("Moon Rover");
rover2.setDirection("SOUTH");
rover2.setXCord(1);
rover2.setYCord(1);
console.log(rover2.where());
console.log(rover2);
There are few questions that I have around this creation.
I want to create an object where the properties/attributes of object are private and not visible to world. Am I successful in doing that? Can I really not access the object attributes?
Is there a better way to create this kind of object?
If I want to inherit this object, I should do a newObject.prototype = roverObjectwill that work? And will that make sense most of all.
Finally I have a wierd problem. Notice the last method of objet "where" which returns a concatenated string. Here I tried following code instead.
newRover.where = function(){
return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
}();
and then did a following console.log
console.log(rover1.where);
console.log(rover2.where);
It threw following error for me:
cannot access optimized closure
Why would it say that? What am I doing wrong?
Thanks for all the help. Any review comments would be appreciated too!
Cheers
Am I successful in doing that? Can I really not access the object attributes?
Indeed. You don't have object attributes, you have local variables in the roverObject function. Local variables can't be accessed from outside, only from the functions inside the roverObject function that have a closure over them.
That you are calling roverObject as a constructor, with new roverObject, is irrelevant, as you are returning a different object from the function. Saying var rover1= roverObject() without the new would do exactly the same thing. Notably the object returned by [new] roverObject is a plain Object as you created it from {}; rover1 instanceof roverObject is false.
If you wanted instanceof to work, you would have to call with new, and use this instead of newRover in the constructor function.
If I want to inherit this object, I should do a newObject.prototype = roverObject will that work? And will that make sense most of all.
No. You currently have no allowance for prototyping. You are using a separate copy of each method for each instance of the roverObject. You can do certainly objects this way but it's a different approach than prototyping. If you wanted to make something like a subclass of roverObject in the arrangement you have now, you'd say something like:
function AdvancedRover() {
var rover= new roverObject();
rover.doResearch= function() {
return rover.where()+' and is doing advanced research';
};
return rover;
}
Note since the ‘private’ local variables in the base class constructor really are private, even the subclass cannot get at them. There's no ‘protected’.
newRover.where = function(){ ... }();
What's that trying to do? I can't get the error you do; all the above does is assigns the string with the location to where (before the setter methods have been called, so it's full of undefineds).
Is there a better way to create this kind of object?
Maybe. see this question for a discussion of class/instance strategies in JavaScript.
Q1: you can create 'private' members in javascript 'classes'. In javascript, privacy is not determined by any access specifier. Instead, access needs to be specifically instrumented. Example:
function MyClass() {
this.val = 100; // public;
var privateVal = 200;
function getVal() { return this.val; } // private method;
this.getPrivateVal = function() { // public method, accessor to private variable
return privateVal;
}
}
Object scope in javascript is governed by a queer concept called closures. AFAIK, there is no parallel concept in any other popular launguage like C+/Java etc.
While I understand what closures are, I cannot put it in words. Perhaps a demonstration will help you:
function closureDemo() {
var done=false;
function setDone() { done=true; }
doLater(setDone);
}
function doLater(func) { setTimeout(func,1000); }
closureDemo();
now, while setDone is called from within doLater, it can still access done in closureDemo, even though done is not in scope (in the conventional procedural sense).
I think you will understand more when you read this.
Q2: I can only say what I do; I don't know if it is better or not. If I wrote your code, it would look like this:
function RoverObject() {
var newRover = {}; // privates
var name;
var xCord;
var ycord;
var direction;
this.setName = function(newName) {
name = newName;
};
this.getName = function() {
return name;
};
this.setDirection = function(newDirection) {
direction = newDirection;
};
// and so on...
this.where = function(){
return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
};
}
var rover1 = new RoverObject();
Points to note:
capitalization of "class name"'s first letter
use of this instead of roverObject
this function is a pure constructor. it returns nothing.
Q3: if you want to do inheritance, then my method (use of this) will not work. Instead, the public methods should be a part of the prototype of RoverObject. Read this. Excellent material.
Hope that helps.
EDIT: There is a problem with the way your code is doing work. Problems:
your function does not do what its name suggests. Its name had better be createRoverObject, because that's exactly what it is doing. It is not working like a class constructor
the methods supported by your class are part of the object, but the data members are not. While this may work (and it is not, as your console.log() problem suggests), it is not a good way to implement a class in javascript. The problem here is of closures. Again, i'm unable to articulate what the problem specifically is, but I can smell it.
With regards to 4. - you are trying to log the function, not the result of calling the function. Should be console.log(rover1.where()); My guess firebug(I assume it's firebug's console.log) does not like to log function definitions.
EDIT Oh I get it, you are actually executing the where funcion when you assign rover.where. Are you trying to get what looks like a property to actually be a function? If that's the case it won't work. It will have to be a function if you want it to be evaluated when it's called.
What happens in you case where gets executed in the constructor function. At that point you are still creating the roverObject closure and hence it's too early to access it's private variables.
This is just addressing point 1 of your post.
Here's a good article on javascript private members and more:
Private Members in JavaScript
Defining your object like this gives you private members.
function RolloverObject() {
var name;
var xCord;
var ycord;
var direction;
this.setName = function(newName) { name = newName; };
this.getName = function() { return name; };
this.setDirection = function(newDirection) { direction = newDirection; };
this.getDirection = function() { return direction; };
this.setXCord = function(newXCord) { xCord = newXCord; };
this.getXCord = function() { return xCord; };
this.setYCord = function(newYCord) { yCord = newYCord; };
this.getYCord = function() { return yCord; };
this.where = function() {
return "Rover :: " + name + " is at Location(" + xCord + "," + yCord + ") pointing to " + direction;
};
}
var rolloverObject = new RolloverObject();

Categories

Resources