Oskar Szura
Oskar Szura

Reputation: 2569

Javascript private functions and object.prototype extend

I have the following angularJS service

define(["angular"], function(Angular) {

var dataStorageService = function() {
    var serviceConstructor = function() {
        var _getColor = function(color) {
            return this.config.categoryColorMapping.colors[color];
        }
    }

    var serviceInstance = new serviceConstructor();

    angular.extend(serviceInstance.prototype, {
        config: {
            numberOfMessagesDisplayed: 5,
            maxTitleLength: 48,
            maxPreambleLength: 140,
            categoryColorMapping: {
                colors : {
                    nyheter: '#2B2B2B',
                    sport: '#F59331',
                    underholding: '#F9B00D'
                },
                categories: {
                    nyheter: _getColor('nyheter'),
                    sport: _getColor('sport'),
                    underholding: _getColor('underholding')
                }
            }
        },
        get: function(param) {
            if(this.config.hasOwnProperty(param)) {
                return this.config[param];
            } else {
                console.warn('Playlist::configService:no "' + param + '" config found');
                return false;
            }
        },
        set: function(param, value) {
            this.config[param] = value;
        }
    });

    return serviceInstance;
};

return dataStorageService;
});

now my goal is to make public the following methods:

  1. get
  2. set

and I want '_getColor' method private but I want to use it within the JSON object config. When I run the code I have

"ReferenceError: _getColor is not defined"

is it possibie to achievie it this way? (to have _getColor private and use it within the JSON object within angular.extend?)

Upvotes: 0

Views: 988

Answers (3)

HMR
HMR

Reputation: 39320

Functions can be shared and still be private, instance specific private members have to be defined in the constructor though. Since your private function doesn't need to access instance specific private members you can do the following:

define(["angular"], function(Angular) {

var dataStorageService = function() {
    var serviceConstructor = function() {
    }

    var serviceInstance = new serviceConstructor();
    //IIFE returning object that will have private members as closure
    // privileged methods have to be in the same function body as the
    // private fucnction
    serviceInstance.prototype = (function() {
        var _getColor = function(instance, color) {
            return instance.config.categoryColorMapping.colors[color];
        };
        return {
          constructor: serviceConstructor
          ,config: {
            numberOfMessagesDisplayed: 5,
            maxTitleLength: 48,
            maxPreambleLength: 140,
            categoryColorMapping: {
                colors : {
                    nyheter: '#2B2B2B',
                    sport: '#F59331',
                    underholding: '#F9B00D'
                },
                categories: {
                    //since categories is a sub object of serviceinstance.categorycolormapper
                    // it is not possible to get the instance of serviceinstance
                    // at this time unless you set it in the constructor
                    // solution could be that each serviceinstance has it's own categorycolormaper
                    // and when categorycolormapper is created pass the serviceinstance instance
                    nyheter: _getColor(this,'nyheter'),
                    sport: _getColor(this, 'sport'),
                    underholding: _getColor(this, 'underholding')
                }
            }
          },
          get: function(param) {
            if(this.config.hasOwnProperty(param)) {
                return this.config[param];
            } else {
                console.warn('Playlist::configService:no "' + param + '" config found');
                return false;
            }
          },
          set: function(param, value) {
            this.config[param] = value;
          }
        }
    }());

    return serviceInstance;
};

return dataStorageService;
});

More info on constructor functions and prototype can be found here: https://stackoverflow.com/a/16063711/1641941

Upvotes: 1

Dinesh
Dinesh

Reputation: 1134

Within the definition of serviceConstructor add following line, after definition of _getColor

serviceConstructor.prototype._getColor = _getColor ;

Upvotes: 0

Alnitak
Alnitak

Reputation: 339955

Functions added to the prototype are defined outside the lexical scope of the constructor, and therefore have no access to "private" methods.

The former are shared between all instances, and the latter are per-instance. The only way to get around this is to explicitly export the (per-instance) function as a property of the instance, making it non-private.

Upvotes: 1

Related Questions