JavaScript Decorator Pattern


I am trying to get a decorator pattern to work follwing

<a href="http://www.joezimjs.com/javascript/javascript-design-patterns-decorator/" rel="nofollow">http://www.joezimjs.com/javascript/javascript-design-patterns-decorator/</a>

I might have missed some point but the pattern does not work as i expect.

If i add two decorators and add them to a class the functions are not passed through as i thought. Only the last decorator's functions can be called or the basic Decorator is called. The chaining is broken. How do i fix this?

I added a fiddle:

<a href="http://jsfiddle.net/hbyLW/25/" rel="nofollow">http://jsfiddle.net/hbyLW/25/</a>

UPDATE: Corrected Version

<a href="http://jsfiddle.net/hbyLW/29/" rel="nofollow">http://jsfiddle.net/hbyLW/29/</a>

And the source code:

// A basic device class var device = function(options) { this.brightness = options.brightness; this.Id = options.Id; this.motion = options.motion; }; // Adding some functions to the class device.prototype = { getID: function() { console.log("This ID:" + this.device.Id); return this.Id; }, getBrightness: function() { console.log("This Brightness: " + this.brightness); return this.brightness; }, getMotion: function() { console.log("This Motion: " + this.motion); return this.motion; } }; // A device Decorator var deviceDecorator = function(device) { this.device = device; }; // Adding pass through functions to the Decorator deviceDecorator.prototype = { getId: function() { console.log("Old Id"); return this.device.getId; }, getBrightness: function() { console.log("Old Brightness"); return this.device.getBrightness; }, getMotion: function() { console.log("Old Motion"); return this.device.getMotion; } }; // A Decorator that adds some functionality to the getBrightness function var brightnessDecorator = function(device) { deviceDecorator.call(this, device); }; brightnessDecorator.prototype = new deviceDecorator(); brightnessDecorator.prototype.getBrightness = function() { this.device.getBrightness(); console.log("Changed Brightness"); }; var motionDecorator = function(device) { deviceDecorator.call(this, device); }; // A Decorator that adds some functionality to the getMotion function motionDecorator.prototype = new deviceDecorator(); motionDecorator.prototype.getMotion = function() { this.device.getMotion(); console.log("changed Motion"); }; // Some options for a device var options = { Id: "Identifier", brightness: true, motion: false }; // Create a new device var Lamp = new device(options); // Add the decorators to the device Lamp = new brightnessDecorator(Lamp); Lamp = new motionDecorator(Lamp); // Executing the functions Lamp.getId(); Lamp.getMotion(); Lamp.getBrightness(); console.log(Lamp);?


Your first decorator returns device.getID (the function itself) rather than calling it and returning the value it returns.

deviceDecorator.prototype = { getID: function() { console.log("Old Id"); return this.device.getID(); // <= call function instead of returning it }, ... }

Also, make sure your capitalization is consistent.


  • How to return an object in my case?
  • what is the diference between cascading and chaining [closed]
  • Django: Serializing a list of multiple, chained models
  • how do you read the ramda docs?
  • wxWidgets: Detecting click event on custom controls
  • Is it possible to send skype chat messages from a linux server without X?
  • IE11 textarea loses focus if another textarea is disabled
  • Is there a way to clone native functions in javascript like window.alert or document.write
  • HighCharts - Show tooltip on column where value is 0 or null
  • ckeditor and jquery UI dialog not working
  • Vuejs: Lifecycle hooks of child routerview components using keep alive
  • cell spacing in div table
  • What causes the runtime difference in this trivial fortran code?
  • Retrieve IP address of device
  • using System.Speech.Synthesis with Windows10 universal app (XAML-C#)
  • Implicit joins and Where in Doctrine - how?
  • Android Activity.onWindowFocusChanged doesn't get called from within TabHost
  • Adding elements to a huge XML file
  • How to define and use opencv mat of user type
  • How to clear text inside text field when radio button is select
  • Why ng-show works with ng-repeat but ng-if doesn't? [duplicate]
  • Get object from AWS S3 as a stream
  • TFS: Get latest causes slow project reloading
  • Cross-Platform Protobuf Serialization
  • Javascript Callbacks with Object constructor
  • Validaiting emails with Net.Mail MailAddress
  • Cassandra Data Model
  • Join two tables and save into third-sql
  • How to make Safari send if-modified-since header?
  • Do I've to free mysql result after storing it?
  • bootstrap to use multiple ng-app
  • retrieve vertices with no linked edge in arangodb
  • using conditional logic : check if record exists; if it does, update it, if not, create it
  • How to get icons for entities from eclipse?
  • Understanding cpu registers
  • Getting Messege Twice Using IMvxMessenger
  • Turn off referential integrity in Derby? is it possible?
  • Add sale price programmatically to product variations
  • JaxB to read class hierarchy
  • Python/Django TangoWithDjango Models and Databases