javascriptprototype-programming

Dynamically change prototype for instance in JavaScript


Is it possible to dynamically append to the prototype of an object's instance? For example, I have two dell objects, one's a laptop and one's a desktop. I want to be able to create two instances of dell and then extend the prototype to either laptop or desktop so I can use the appropriate getters / setters.

JSFiddle link: http://jsfiddle.net/QqXgV/1/

var dell = function(){}
dell.prototype = new computer();
dell.prototype.constructor = dell;

var hp = function(){}
hp.prototype = new computer();
hp.prototype.constructor = hp;

var computer = function(){}
computer.prototype.setType = function(type){
  //Here is where I would extend.
  this.prototype extends window[type].prototype;
}

var laptop = function(){}
laptop.prototype.getKeyboard = function(){
  return "motherboard";
}

var desktop = function(){}
desktop.prototype.getKeyboard = function(){
  return "usb";
}

var dellDesktop = new dell();
dellDesktop.setType("desktop");

var dellLaptop = new dell();
dellLaptop.setType("laptop");

//This is the end goal.
dellDesktop.getKeyboard(); //Returns usb
dellLaptop.getKeyboard(); //Returns motherboard
//And then be able to do the same thing with hp.

Solution

  • In a case where a Dell can be either a Laptop or a Desktop one might create a DellLaptop and a DellDesktop constructor. But Laptops come in ultrabooks and netbooks so one has to create DellLaptopUltrabook and DellLaptopNetBook. So in a case where something can be either this or that and other objects can be this or that (like HP can also be either Laptop or Desktop) maybe the following pattern can help out:

    var Computer = function(){};
    //proxy getKeyboard based on what type it is
    Computer.prototype.getKeyboard = function(){
      return this.type.getKeyboard.call(this);
    };
    
    var Dell = function(args){
      //do some checks on args here
      //re use Computer constructor
      Computer.call(this.args);
      //re use laptop or Desktop constructor code
      args.type.call(this,args);
      //re use Laptop or Desktop protype members
      this.type=args.type.prototype;
    
    };
    Dell.prototype = Object.create(Computer.prototype);
    Dell.prototype.constructor = Dell;
    
    var Laptop = function(){};
    Laptop.prototype.getKeyboard = function(){
      return "motherboard";
    };
    //ultrabook and netbook can inherit from Laptop
    //  so you could pass UltraBook or Netbook as type
    
    
    var Desktop = function(){};
    Desktop.prototype.getKeyboard = function(){
      return "usb";
    };
    
    var dellDesktop = new Dell({type:Desktop});
    
    var dellLaptop = new Dell({type:Laptop});
    
    //This is the end goal.
    console.log(dellDesktop.getKeyboard()); //Returns usb
    console.log(dellLaptop.getKeyboard()); //Returns motherboard