USING OBEJCT IN NODE JS




 

 WORKING WITH NODE USING OOPS CONCEPTS                          

   Class pattern

// Constructor
function Foo(bar) {
  // always initialize all instance properties
  this.bar = bar;
  this.baz = 'baz'; // default value
}
// class methods
Foo.prototype.fooBar = function() {

};
// export the class
module.exports = Foo;
Instantiating a class is simple:
// constructor call
var object = new Foo('Hello');
Note that I recommend using function Foo() { ... } for constructors instead ofvar Foo = function() { ... }.
The main benefit is that you get better stack traces from Node when you use a named function. Generating a stack trace from an object with an unnamed constructor function:
var Foo = function() { };
Foo.prototype.bar = function() { console.trace(); };

var f = new Foo();
f.bar();
... produces something like this:
Trace:
    at [object Object].bar (/home/m/mnt/book/code/06_oop/constructors.js:3:11)
    at Object. (/home/m/mnt/book/code/06_oop/constructors.js:7:3)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)
... while using a named function
function Baz() { };
Baz.prototype.bar = function() { console.trace(); };

var b = new Baz();
b.bar();
... produces a stack trace with the name of the class:
Trace:
    at Baz.bar (/home/m/mnt/book/code/06_oop/constructors.js:11:11)
    at Object. (/home/m/mnt/book/code/06_oop/constructors.js:15:3)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)
To add private shared (among all instances of the class) variables, add them to the top level of the module:
// Private variable
var total = 0;

// Constructor
function Foo() {
  // access private shared variable
  total++;
};
// Expose a getter (could also expose a setter to make it a public variable)
Foo.prototype.getTotalObjects = function(){
  return total;
};

Avoid assigning variables to prototypes

If you want to define a default value for a property of an instance, define it in the constructor function.
Prototypes should not have properties that are not functions, because prototype properties that are not primitives (such as arrays and objects) will not behave as one would expect, since they will use the instance that is looked up from the prototype. Example for Dimitry Sosnikov's site:
var Foo = function (name) { this.name = name; };
Foo.prototype.data = [1, 2, 3]; // setting a non-primitive property
Foo.prototype.showData = function () { console.log(this.name, this.data); };

var foo1 = new Foo("foo1");
var foo2 = new Foo("foo2");

// both instances use the same default value of data
foo1.showData(); // "foo1", [1, 2, 3]
foo2.showData(); // "foo2", [1, 2, 3]

// however, if we change the data from one instance
foo1.data.push(4);

// it mirrors on the second instance
foo1.showData(); // "foo1", [1, 2, 3, 4]
foo2.showData(); // "foo2", [1, 2, 3, 4]
  1. LOG "foo1" [1,2,3]
  2. LOG "foo2" [1,2,3]
  3. LOG "foo1" [1,2,3,4]
  4. LOG "foo2" [1,2,3,4]

Hence prototypes should only define methods, not data.
If you set the variable in the constructor, then you will get the behavior you expect:
function Foo(name) {
  this.name = name;
  this.data = [1, 2, 3]; // setting a non-primitive property
};
Foo.prototype.showData = function () { console.log(this.name, this.data); };
var foo1 = new Foo("foo1");
var foo2 = new Foo("foo2");
foo1.data.push(4);
foo1.showData(); // "foo1", [1, 2, 3, 4]
foo2.showData(); // "foo2", [1, 2, 3]

    Don't construct by returning objects - use prototype and new

    For example, construction pattern which returns an object is terrible (even thoughit was introduced in "JavaScript: The Good Parts"):
    function Phone(phoneNumber) {
      var that = {};
      // You are constructing a custom object on every call!
      that.getPhoneNumber = function() {
        return phoneNumber;
      };
      return that;
    };
    // or
    function Phone() {
      // You are constructing a custom object on every call!
      return {
        getPhoneNumber: function() { ... }
      };
    };
    Here, every time we run Phone(), a new object is created with a new property. The V8 runtime cannot optimize this case, since there is no indication that instances of Phone are a class; they look like custom objects to the engine since prototypes are not used. This leads to slower performance.
    It's also broken in another way: you cannot change the prototype properties of all instances of Phone, since they do not have a common ancestor/prototype object. Prototypes exists for a reason, so use the class pattern described earlier.

    1 Comments