1

Let's say we inherit 90% of code functionality from a boilerplate prototype-based funciton:

var BoilerplateForOtherFunctions = function(){};

BoilerplateForOtherFunctions.prototype.addOneYear = function(){
  return this.myAge += 1;
};

BoilerplateForOtherFunctions.prototype.getAge = function(myUrl){
  return this.myAge;
};



And we have many functions that inherits this prototype and used it like this:

var MyNormalFnOne = function(){
  this.myAge = "34";
  console.log( this.getAge() );
  this.addOneYear();
};

// only injects the boilerplate object into our function
underscore.extend(MyNormalFnOne.prototype, BoilerplateForOtherFunctions.prototype);

new MyNormalFnOne();



Everything works well.

Problem is - that we rely on a fact, that someone has defined this.myAge before we use anything from the boilerplate prototype. This is very common solution of programming in Javascript.

Wouldn't be better to pass all arguments into the prototype fn and be more functional? It would lead to faster debugging, allows function cashing, creates less coding mistakes and program errors.



Into something like this (more functional approach):

var BoilerplateForOtherFunctions = function(){};

BoilerplateForOtherFunctions.prototype.addOneYear = function(age){
  return age += 1;
};

BoilerplateForOtherFunctions.prototype.getAge = function(age){
  return age; // makes no sense, here - just a sample, of course
};


var MyNormalFnOne = function(){
  var myAge = "34";
  console.log( this.getAge(myAge) );
  myAge = this.addOneYear(myAge);
};

// only injects the boilerplate object into our function
underscore.extend(MyNormalFnOne.prototype, BoilerplateForOtherFunctions.prototype);

new MyNormalFnOne();



The problem with second appoarch is (with a functional one)
- passing many arguments to every function
- return value must be assigned again, it doesn't "magically" work

The problem with first appoarch is (with a traditionals)
- difficult debugging, not reliable code, no fn cashing, ...




Any opinion?

Samuel O
  • 2,258
  • 1
  • 16
  • 26

1 Answers1

0

The constructor function is there to initialize instance specific members and the prototype is for shared members (like functionality).

Since your prototype assumes myAge to exist you should set it in BoilerplateForOtherFunctions and re use it in types that inherit from it:

var BoilerplateForOtherFunctions = function(args){
  args=args||{};
  this.myAge = args.myAge === 0? 0 ://either 0
     args.myAge || 10;//or 10 when not set
};

BoilerplateForOtherFunctions.prototype.addOneYear = function(){
  return this.myAge += 1;
};

BoilerplateForOtherFunctions.prototype.getAge = function(myUrl){
  return this.myAge;
};

var MyNormalFnOne = function(args){
  //re using parent constructor
  BoilerplateForOtherFunctions.call(this,args);
  console.log( this.getAge() );
  this.addOneYear();
};

// use Object.create will have instances of MyNormalFnOne be an instanceof BoilerplateForOtherFunctions
MyNormalFnOne.prototype = Object.create(BoilerplateForOtherFunctions.prototype);
//repair prototype.constructor after assigning a new value to prototype
MyNormalFnOne.prototype.constructor = MyNormalFnOne;

var oneFirst = new MyNormalFnOne();
var oneSecond = new MyNormalFnOne({myAge:22});

More info on constructor functions and prototype here: Prototypical inheritance - writing up

Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160