简体   繁体   中英

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?)

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.

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

serviceConstructor的定义内,在_getColor的定义后添加以下行

serviceConstructor.prototype._getColor = _getColor ;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM