Elegant way to export variables from module in Nodejs - javascript

I want to export one variable after initialized by parameters from one module in Node.js.
Now, there are three options for me.
Option 1: with exports directly
// moduletest.js
exports.init = function(v, w) {
// actually, the value of a and b could be initialized by other functions.
// here is one example, simply assign them with v and w just for test
exports.a = v;
exports.b = w;
}
The variable a and b could be used out of the module.
// app.js
require('./moduletest').init(3, 1);
var ff = require('./moduletest');
console.log(ff.a);
console.log(ff.b);
Option 2: var one get method in the object.
var MyObject = {
init: function(a, b) {
this._a_ = a;
this._b_ = b;
},
getA: function () {
return this._a_;
},
};
exports.mod = {
valA: MyObject.getA,
init: MyObject.init
}
The variable _a_ could be accessed by getA method.
Option 3: through one get method in the function prototype.
var Test = function (a, b){
this._a_ = a;
this._b_ = b;
};
Test.prototype.getA = function()
{
return this._a_;
}
exports.mod = Test;
Here I have two questions:
Which one is more elegant way to do that?
If none of above three options is better, is there any better ways?

Based on the comments to your question, a possible approach is the one below. Yours have mainly the problem that you don't actually hide the data, thus letting the user to modify them.
module.exports = function (_a, _b) {
return function() {
var obj = { };
Object.defineProperty(obj, 'a', {
get: function () { return _a; }
});
Object.defineProperty(obj, 'b', {
get: function () { return _b; }
});
};
}
You can use it as it follows:
var factory = require('file_above')(your_a, your_b);
// code
var instance = factory();
// you cannot modify a or b on instance!!
Something similar can be done by using the bind method of a function and so on. Keep in mind that there is a plenty of possible solutions and none of them is the right one, while almost all of them are valid ones.
As far as I see, anyway, the ones you posted above have some minor issues, even though all of them work fine, of course.

Related

Declaring properties before using them - best practice?

I always declare properties on objects if i know i will use them in my code at some point (To help other developers not be surprised when a new property gets added onto an object in debugging process and wonder where or why it has been populated):
var TestHelper = function(){
var Test = function(){
// Public:
this.a = null; // string
this.b = null; // number
}
// Public:
return {
/*Test*/ TestFunction: function(str, num){
var test = new Test();
test.a = s;
test.b = num;
return test;
}
}
}
I can find it frustrating when i come across code like this:
var TestHelper = function(){
var Test = {};
// Public:
return {
/*Test*/ TestFunction: function(str, num){
var test = new Test();
test.a = s;
test.b = num;
return test;
}
}
}
or even harder (losing the javascript type that's helpful for debugging)
var TestHelper = function(){
// Public:
return {
/*{}*/ TestFunction: function(str, num){
return {
a = s,
b = num
}
}
}
}
... because it makes it just that bit harder to understand fully what the original developer had in mind.
Ignoring my opinion,
What are the various thoughts on this and why?
Do big teams generally like to declare properties first to help other developers, or visa versa?
Am i asking the right question or is there another point i am missing?
Of course developers prefer things documented it's easier for them.
A good practice in Javascript is to avoid undefined value, so for this it's far better to initialize your objects with null value, or empty array or empty objects.
However you forget a thing with your last case -> this approach when possible is the best :
function Test(str, num){
this.a=str;
this.b=num;
return this;
}
Test.prototype.method = function(a){...}//adding method to the object Test
var test = new Test("toto", 5);
test.method(a);//executing method

Get reference to method function by name?

I want to store a function, internal to the function-object its within, in an object member, but I need to get access to it via name. The code below makes it easier to understand...
// MyClassThing.js:
var MyClassThing = (function() {
var _ref = {obj: undefined, fnc: undefined};
function setup(domObject, refName) {
_ref.obj = domObject;
_ref.fnc = this['func_' + refName]; // <<-- This does not work!!
}
function doThing() {
if(_ref.func)
_ref.fnc();
}
function func_foo() {
console.log('Foo!');
}
return {
setup: setup,
doThing: doThing
};
})();
// index.html
<script>
MyClassThing.setup($('#fooObj'), 'foo');
MyClassThing.doThing();
</script>
What do I do to get _ref.fnc = ???? to work properly?
You will have to use helper object to put methods as its properties. Then you will be able to refer to them by variable name:
var MyClassThing = (function () {
var _ref = { obj: undefined, fnc: undefined },
methods = {};
function setup(domObject, refName) {
_ref.obj = domObject;
_ref.fnc = methods['func_' + refName];
}
function doThing () {
if (_ref.fnc) _ref.fnc();
}
methods.func_foo = function () {
console.log('Foo!');
};
return {
setup: setup,
doThing: doThing
};
})();
You can't use this because it points to the object returned from IIFE, however your methods of interest are not properties of this object.
There's a typo in your code:
var MyClassThing = (function() {
var _ref = {obj: undefined, fnc: undefined};
function setup(domObject, refName) {
_ref.obj = domObject;
_ref.fnc = this['func_' + refName]; // <<-- This does not work!!
}
function doThing() {
if(_ref.fnc)
_ref.fnc();
}
function func_foo() {
console.log('Foo!');
}
return {
setup: setup,
doThing: doThing
};
})();
In your doThing function, you are checking for the existency of a _ref.func instead of _ref.fnc
To achieve what you want to do, you need to understand that the functions you are declaring using the "function" are not linked to the class. There's no notion of "private member function" in javascript. If you want to bind a function to a class, you need to declare it like this (there are other ways, i'm just showing you one of them) :
MyClassThing.prototype.func_foo = function () {
}
The best thing to do, in your case, would be to set _ref.fnc to func_foo directly. If you want to keep the this context, take a look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

How do we create instances of a class in JavaScript using new operator and factory pattern?

I am trying to make a class (called Foo) like object in JavaScript that would let me create multiple instances of Foo. By multiple instances, I mean, each instance would maintain separate internal state. This is how I am achieving it.
var Foo = function() {
function init(a) {
this.a = a
}
function state() {
return this.a
}
function getFoo() {
return {
init: init,
state: state
}
}
return {
getFoo: getFoo
}
}()
var a = Foo.getFoo()
var b = Foo.getFoo()
a.init(10)
b.init(20)
alert(a.state() + ', ' + b.state())
As you can see that the Foo.getFoo() seems to simulate the Factory pattern usually used in Java. The internal state is the variable this.a. I consider my attempt a success because a.state() and b.state() display two different internal states. However, this is purely my attempt without any knowledge of how these things are implemented in the industry.
Now, my questions may seem like a request for code review and is at the risk of getting closed, so I will try to make my questions as objective as possible.
How can the same code be implemented such that new operator can be used instead to create the new instances of a class with this.a as the internal state?
How is my code with the factory pattern written in the industry?
var Foo = function (a) {
this.a = a;
};
Foo.prototype.state = function () {
return this.a;
};
var a = new Foo(10);
a.state(); // 10
Bun you can also declare the state method from constructor itself like:
var Foo = function (a) {
this.a = a;
this.state = function () {
return this.a;
};
};
UPDATE: Factory pattern.
I usually use this for my factories:
var Foo = function (a) {
this.a = a;
};
Foo.prototype.state = function () {
return this.a;
};
var FooFactory = function () {};
FooFactory.prototype.create = function (a) {
return new Foo(a);
};
var factory = new FooFactory();
var a = factory.create(20);
a instanceOf Foo; // true
a.state(); // 20

Is this kind of chaining possible in JavaScript?

I'm working on a file manager framework similar to elFinder. My current code works fine but now I want to make it look better and add chaining (I'm not sure if it's chaining or decorator pattern).
Here is a sample of what I want to do:
function UI() {}
UI.prototype.folders = function(){
return [];
}
UI.prototype.folders.prototype.getSelectedFolder = function(){
return {};
}
Calling UI.folders() should return an array of folder objects. So if you call UI.folders() you would get something similar to this:
[
Object { name="folder1", selected=false },
Object { name="folder2", selected=false },
Object { name="folder3", selected=true }
]
And calling UI.folders().getSelectedFolder() would filter the results from UI.folders() and will return:
Object { name="folder3", selected=true }
Is this possible? Is it right to say "chaining" in this case or it's "decorative pattern"?
If it's not - is there another more appropriate way to do it?
Any help wold be really appreciated!
The code in your question isn't reflective of a proper implementation, but to answer your direct questions, yes, this...
UI.folders().getSelectedFolder()
...would be an example of method chaining.
A decorator pattern is different. If you have a set of methods, and each one should always first invoke some common function, you can create a decorator that will return a function that first calls the common one, then the actual one...
function foo() {
console.log('I\'m foo, and I\'m first, and I was given these args:', arguments);
}
function decorateWithFoo(decorated) {
return function () {
foo.apply(this, arguments);
decorated.apply(this, arguments);
};
}
So you can use decorateWithFoo to create a function that always invokes foo first...
// create and decorate bar()
var bar = function(a,b) {
console.log('I\'m bar, and I was called after "foo", and was given args:', a, b);
};
bar = decorateWithFoo(bar);
bar(123, 456); // this will first call `foo()`, then (the original) `bar()`.
// create and decorate baz()
var baz = function(a,b) {
console.log('I\'m baz, and I was called after "foo", and was given args:', a, b);
};
baz = decorateWithFoo(baz);
baz(123, 456); // this will first call `foo()`, then (the original) `baz()`.
Some languages have built in syntax for creating decorators. JavaScript currently does not.
If you find yourself using decorators in different ways, you could create another function that sets up the initial decorator function...
function generateDecorator(decorator) {
return function (decorated) {
return function () {
decorator.apply(this, arguments);
decorated.apply(this, arguments);
};
};
}
So our original decoreateWithFoo could have been set up like this...
function foo() {
console.log('I\'m foo, and I\'m first, and I was given these args:', arguments);
}
var decorateWithFoo = generateDecorator(foo);
To make this work properly, you need to make your folders method be a function that returns an object that inherits from an array.:
UI.prototype.folders = function(){
// must return an object that inherits from an array
// that has the additional methods on it you want like getSelectedFolder()
}
The are a few different ways to solve this. The primary goal is that when you call a function you get an object/function back that is the same type of object with different properties. I'm not a fan of the prototype usage so I would do it like this (this is one way to solve it):
var FolderList = function ()
{
var _folders = [];
folders.pop({ name: "folder1", selected: false });
folders.pop({ name: "folder2", selected: true });
folders.pop({ name: "folder3", selected: false });
// prevent other programers from changing _folders
// which would break this, so just use a function
this.folders = function ()
{
return _folders;
}
this.selectedFolders = function ()
{
var tmpFolders = [];
for (var folderIndex = 0;
folderIndex < this._folders.length;
folderIndex++)
{
if (this._folders[folderIndex].selected)
{
tmpFolders.pop(_folders[folderIndex]);
}
}
_folders = tmpFolders;
return this;
}
this.addFolder = function (folder)
{
_folders.pop(folder);
return this;
}
};
var folderList = new FolderList();
folderList.selectedFolders()
.addFolder({ name: "folder1", selected: false })
.addFolder({ name: "folder3", selected: true })
.selectedFolders();
// array of 2 objects, folder2 and folder3
var arrayOfSelectedFolder = folderList.folders();

jS OOP nested functions

Ok this may be a noobolicious question as im new to OOP.
Im attempting to build something of a JS Object Library and was wondering if I could do it using nested functions??
var object = new function() {
this.action1 = function () {
this.dostuff1 = function () {
return "dostuff1";
};
this.dostuff2 = function () {
return "dostuff2";
};
};
I am having trouble accessing the third level functions. Can I nest like this?
this.action2 = function () {
return "action2";
};
alert(object.action1.dostuff2());
While Eberlin's answer is perfectly correct I'd suggest you to create a nested object which in turn again exposes functions rather than nesting functions itself. Otherwise this might become a maintainability nightmare.
Basically you could create
var Child = function(){
//constructor
};
Child.prototype.doStuff2 = function(){
return "dostuff2";
};
var Root = function(obj){
//constructor
this.child = obj;
};
Root.prototype.action1 = function(){
return "doStuff1";
};
//usage
var myRoot = new Root(new Child());
myRoot.action1();
myRoot.child.action2();
Here's a live example: http://jsbin.com/ijotup/edit#javascript,live
See below for some code cleanup:
var o = (new function () { // changed 'object' to 'o'
this.action1 = (function () { // added parentheses, not required.
this.dostuff1 = (function () { // does not return anything.
return "dostuff1"; // and is also not the proper way to organize
}); // ** look at the javascript prototype
return this; // now it does
}); // missing closing bracket
this.dostuff2 = (function () {
return "dostuff2";
});
});
alert(o.action1().dostuff2()); // action1 is a function, not a variable.
Hope this helps. Also, here's a brief tutorial on the javascript prototype.

Categories