Data Model Definition Standard in JavaScript/Node

483 views
Skip to first unread message

Prabhash Rathore

unread,
Jan 6, 2015, 7:19:32 PM1/6/15
to nod...@googlegroups.com

I recently started programming in JavaScript (Server side) and Node.js. I come from Java background where there is a concrete standard on how you define Data Object, which is Java Bean. Do we have any such standards in JavaScript/Node on how we define Data Objects (similar to Java Beans)?

I have researched at many places and couldn't find any standards. I have seen following styles but not sure which is better or recommended:

//bean1.js
module.exports = function() {
var obj = {};
obj.name = '';
obj.department = '';

return obj;

}

//bean2.js
module.exports = function() {

this.name = '';
this.department = '';

return this;

}

//bean3.js
module.exports = function(param) {
var obj = {};

if(param === undefined) {
return obj;
}

obj.name = param.name;
obj.department = param.department;

return obj;

}

//bean4.js
module.exports = {
    name : '';
    department : '';
}

Aria Stewart

unread,
Jan 6, 2015, 7:33:34 PM1/6/15
to nod...@googlegroups.com
On Jan 6, 2015, at 7:19 PM, Prabhash Rathore <prabhas...@gmail.com> wrote:

I recently started programming in JavaScript (Server side) and Node.js. I come from Java background where there is a concrete standard on how you define Data Object, which is Java Bean. Do we have any such standards in JavaScript/Node on how we define Data Objects (similar to Java Beans)

[snip]


//bean4.js
module.exports = {
    name : '';
    department : '';
}

All of them work, just a plain object literal is my favorite. They're so trivial that there's no name for them in Javascript other than "an object". "Just make an object".

If you need to make it a requireable module, what you posted there is exactly it. If it varies over the life of your program, then you'd probably read it as a file and JSON.parse instead. Either way, the result is an object you can pass around.

Aria

Rick Waldron

unread,
Jan 6, 2015, 7:35:03 PM1/6/15
to nod...@googlegroups.com
This has nothing to do with Node. The disparity in patterns you're seeing is in language experience. "bean1.js" and "bean3.js" are just explicitly doing what "bean2.js" does for implicitly: allocate an instance object. "bean4.js" is not a comparable pattern to 1, 2 and 3 in the initialization sense: it's an instance of the built-in Object whose properties are being used to expose multiple "exports", whereas 1, 2, 3 use a function to export a single function object "export". 

Rick

--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/85a3bdc4-83af-4c8a-979d-5d527eee8695%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Prabhash Rathore

unread,
Jan 10, 2015, 5:04:21 AM1/10/15
to nod...@googlegroups.com
Thanks Aria/Rick for your replies!

I understand bean1, bean2 and bean3 are similar and they do the same thing. What I was looking for is a standard way of creating data object but it seems like it's more of a free-style and we can use any of the style to create data objects.

Based on your replies, I think this is the best way to represent a data object as it's just data and object can represent this data:
module.exports = {
    name : '';
    department : '';
}
However I have noticed people using function() to create data objects and then they just return an object inside the function (see below example)? Is there any specific use case or reason on using function instead of using just object literal?
   module.exports = function() {
     return {
       name : 'abc',
       city : 'sj'

Alexander Praetorius

unread,
Jan 10, 2015, 10:08:31 AM1/10/15
to nod...@googlegroups.com
if you just export an object, you gain access to exactly that object wherever you require it (singleton)
if you export a function which returns an object, you gain access to a copy of that object wherever you require and execute it (factory?)

--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.

Kevin Ingwersen (Ingwie Phoenix)

unread,
Jan 10, 2015, 10:08:47 AM1/10/15
to nod...@googlegroups.com
Hey Prabhash!

Using functions to return objects tends to be known as „generators“ or „factories“. You could also call it a pseudo-constructor. This method is used to create more dynamic objects. Imagine you had this data model that could pick up information off some kind of configuration file - you’d end up with something like:

module.exports = function(fileName) {
    var data = parseMyConfig(fileName);
    return {…};
}

// ravi

unread,
Jan 10, 2015, 2:30:24 PM1/10/15
to nod...@googlegroups.com
On Jan 10, 2015, at 5:04 AM, Prabhash Rathore <prabhas...@gmail.com> wrote:
>
> Based on your replies, I think this is the best way to represent a data object as it's just data and object can represent this data:
> module.exports = {
>
> name
> : '';
>
> department
> : '';
> }
> However I have noticed people using function() to create data objects and then they just return an object inside the function (see below example)? Is there any specific use case or reason on using function instead of using just object literal?



It depends on what it is you want your module to offer. Say the module provides a bunch of utility functions. Then you may just choose to export each function and be done:

str_utils.js:

exports.uncamelcase = function(str) { …. };
exports.is_palindrome = function(str) { …. };
exports.is_numeric = function(str) { …. };

Then someone can use it thus:

var str_utils = require(‘str_utils’);

if( str_utils.is_palindrome(person_name) === true )
console.log(“Well, aren’t you special!”);

On the other hand, if your module returns a constructor/class to be used for instantiating new objects, then you may wish to do this:

module.exports = Car;

function Car(name, cost, mpg, alternative)
{
this.name = name;
this.cost = cost;
this.env_damage = mpg;
this.alternative = alternative;
}

Car.prototype.appeal =
function()
{
return(this.cost/this.mpg);
};

Car.prototype.snark =
function()
{
return(this.alternative.advise());
};

Then someone could:

var Car = require(‘car’);
var metro = require(‘metro’);

var new_car = new Car(‘Hummer’, 80000, 2, metro);

if( new_car.appeal() > 700 )
console.log(“Congratulations on your fancy”, new_car.name, “but”, new_car.snark());

Etc. Keep in mind the part played by require/module caching (if you return an object, it will be cached and returned from the cache at the next require — this may or may not be what you want: I use it as a way to load dependencies without passing them around).

—ravi


Alexander Praetorius

unread,
Jan 11, 2015, 1:44:38 PM1/11/15
to nod...@googlegroups.com
Many people use "this", "prototype" and "new", like:

module.exports = function Car (name, cost, mpg, alternative) {
  this.name = name;
  this.cost = cost;
  this.env_damage = mpg;
  this.alternative  = alternative;
};
Car.prototype.appeal = function() {
  return(this.cost/this.mpg);
};
Car.prototype.snark = function() {
  return(this.alternative.advise());
};

I think that is very "beginner unfriendly" and a lot of people i know got very confused by
"prototypes" and the different way "this" can be set and how it can trip you over.
And i remember a time when i wanted to transform an instance after creation, but
had no influence over all the many places which used "new Name(...)", so i kinf of
dislike the use of "new" too.
I wonder if it would be bad to get rid of those and instead write the car module like:


module.exports = function Car (name, cost, mpg, alternative) {
  var api = {
    name: name,
    cost: cost,
    env_damage: mpg,
    alternative: alternative,
    appeal: function appeal () { api.cost / api.mpg; },
    snark: function snark  () { api.alternative.advise(); }
  };
  return api;
};



--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.

Matt

unread,
Jan 11, 2015, 6:36:01 PM1/11/15
to nod...@googlegroups.com
If you do that you probably lose some of the performance enhancements V8 does by converting things internally to classes.

Alexander Praetorius

unread,
Jan 12, 2015, 11:03:59 AM1/12/15
to nod...@googlegroups.com
how bad would that be?
Could it end up to be the "performance bottleneck" easily? Because maybe it doesnt matter so much?
In the end, i feel that it would make things a lot more readable, by getting rid of the need to use 3 "keywords":
"new", "prototype" and "this".

According to jsperf, the "closure method" is even way faster...
=> http://jsperf.com/prototypemodule-vs-closuremodule

Maybe that test has to be refined?


// ravi

unread,
Jan 12, 2015, 12:27:28 PM1/12/15
to nod...@googlegroups.com
On Jan 12, 2015, at 11:00 AM, Alexander Praetorius <d...@serapath.de> wrote:
>
> how bad would that be?


I think Trevor Norris had a blog post about this, but I cannot find it, sorry… I tend to confuse the names of JS/NodeJS heavies… maybe it was someone else :-).

—ravi
> To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/CAN5%2BLUsPdt694cCFmY1%2BUF%3Ds_%3DcCWDmUS4ozACzd2zez525N%2BA%40mail.gmail.com.

jules

unread,
Jan 13, 2015, 1:32:13 AM1/13/15
to nod...@googlegroups.com
Le lundi 12 janvier 2015, 17:00:21 Alexander Praetorius a écrit :
> Maybe that test has to be refined?

like this?
http://jsperf.com/prototypemodule-vs-closuremodule/6

v8 made some optimizations on "prototype" way

Alexander Praetorius

unread,
Jan 13, 2015, 10:17:52 PM1/13/15
to nod...@googlegroups.com
it seems, that the closure way is faster.
it was just the creation of functions whenever the closure was executed,
while the prototype version uses the same function,
so a proper comparison would be:
http://jsperf.com/prototypemodule-vs-closuremodule/9
i used
"var api = {...};" just to reference "api.x" in methods
even though it still gets rid of "prototype" and "new", it still uses "this" :-(

But maybe in a real world example, if i would just replace methods like:
        appeal: appeal,
        snark: snark
with something like
        appeal: function () { return appeal(api); },
        snark: function () {return snark(api); }
of course with the need to adapt "appeal" and "snark" accordingly by replacing "this" with "api",
it should not matter much anymore, right?
after all - its still quite fast and at least i got rid of "this" :-)




--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.

// ravi

unread,
Jan 14, 2015, 10:48:49 AM1/14/15
to nod...@googlegroups.com
On Jan 13, 2015, at 9:58 PM, Alexander Praetorius <d...@serapath.de> wrote:
>
> it seems, that the closure way is faster.
> it was just the creation of functions whenever the closure was executed,
> while the prototype version uses the same function,


But that is the key difference, as you write below:


> But maybe in a real world example, if i would just replace methods like:
> appeal: appeal,
> snark: snark
> with something like
> appeal: function () { return appeal(api); },
> snark: function () {return snark(api); }


Or am I missing something?

You are not creating a closure (closing over something), without some anonymous functions.

—ravi


jules

unread,
Jan 14, 2015, 10:49:12 AM1/14/15
to nod...@googlegroups.com
Car.prototype.appeal = appeal;

function is outside prototype, which slowed the process

http://jsperf.com/prototypemodule-vs-closuremodule/10

but it seems thats better for closure
http://jsperf.com/prototypemodule-vs-closuremodule/11

jules



Alexander Praetorius

unread,
Jan 14, 2015, 10:25:38 PM1/14/15
to nod...@googlegroups.com
but it seems thats better for closure
http://jsperf.com/prototypemodule-vs-closuremodule/11


If i run http://jsperf.com/prototypemodule-vs-closuremodule/11 a couple of times, even though speed of closure and prototype version are close to each other, closure most often ends up being slightly faster.


@ // ravi
So basically i get the same stuff with closure, that i get with prototype and at same speed, right?
=> but without the need for "new" and "prototype"

I'm kind of still relying on "this", but if i want to use private scope, afaik,
prototype methods wont help me anyway and i need to use the same style i used with the closure style before,
for example:

    function Car(name, cost, mpg, alternative) {
      var _x = 5;
      this.getX = function () { return _x; };

      this.name = name;
      this.cost = cost;
      this.env_damage = mpg;
      this.alternative = alternative;
    }

    (new Car()).getX();

vs.

    function closureCar(name, cost, mpg, alternative) {
          var _x = 5;
          return { getX: function () { return _x; },

            name: name,
            cost: cost,
            env_damage: mpg,
            alternative: alternative
          };
    } closureCar().getX();

I still have a strong feeling, that the closureCar, which doesnt use "new" and doesnt use "prototype" is far easier to understand.
Sad thing is, that it seems to not be possible to get rid of "this" without some negative performance implications :-/

Prabhash Rathore

unread,
Feb 1, 2015, 3:44:49 AM2/1/15
to nod...@googlegroups.com
Thank you everyone for all your replies! This is very helpful! I had posted this question on StackOverflow too so I am going to update StackOverflow based on the information from this thread. Thank you again!


On Tuesday, January 6, 2015 at 4:19:32 PM UTC-8, Prabhash Rathore wrote:
Reply all
Reply to author
Forward
0 new messages