Nikola Stojaković
Nikola Stojaković

Reputation: 2305

Changing JavaScript object on function's result

I have made this function:

var changeFilter = ( function (filterName, filterValue) {

  var filters = {
    "tip-oglasa":           "",
    "zemlja":               "",
    "grad":                 "",
    "deo-grada":            "",
    "min-kvadrata":         "",
    "max-kvadrata":         "",
    "min-soba":             "",
    "max-soba":             "",
    "min-spratova":         "",
    "max-spratova":         "",
    "min-godina-izgradnje": "",
    "max-godina-izgradnje": ""
  };

  return function () { 
    filters[filterName] = filterValue; 
    return filters;
  };

})();

I want to have function in which object filters will be defined, and get / change it via two functions (getFilters, which will just get the filters variable and changeFilter which will change filters variable and return the result).

Is is it possible to do something like this? I don't want to make filters object public as I want to access it only via this two methods.

Upvotes: 0

Views: 76

Answers (2)

cdhowie
cdhowie

Reputation: 168988

Sure, just return an object literal with functions, which will act as methods:

var filtersProxy = ( function () {
  var filters = {
    "tip-oglasa":           "",
    "zemlja":               "",
    "grad":                 "",
    "deo-grada":            "",
    "min-kvadrata":         "",
    "max-kvadrata":         "",
    "min-soba":             "",
    "max-soba":             "",
    "min-spratova":         "",
    "max-spratova":         "",
    "min-godina-izgradnje": "",
    "max-godina-izgradnje": ""
  };


  return {
    getFilters: function getFilters() {
      return filters;
    },

    changeFilter: function changeFilter(filterName, filterValue) {
      filters[filterName] = filterValue;
      return filters;
    }
  };
})();

A few things to note about this particular example:

  • filtersProxy.getFilters() will return a reference to the filters object directly, and changes to this object will be reflected through the filters variable. That is, someone could do filtersProxy.getFilters().foo = 'bar' and mutate it. Possible solutions:
    • Return a copy of the object, so that the caller can change the object you give them without changing filters.
    • Provide an accessor getFilter(key) that returns the value at the specified object attribute.
  • You have the same problem with filtersProxy.changeFilter(), which returns filters. Here you could just return this to return the proxy object, and allow chaining: filtersProxy.changeFilter('foo', 'bar').changeFilter('bar', 'baz').getFilter('baz').
  • I moved the parameters from the IIFE to the changeFilter method, as that's where they really belong.
  • Considering that you provide both get and set accessors, and no filtering/validation, there's no advantage to doing things this way versus directly using an object, unless you are planning on adding some validation or other logic in your getters and setters.

Upvotes: 1

Spencer Wieczorek
Spencer Wieczorek

Reputation: 21565

Certainly, for example you can have the variable "private" or only accessible within the function scope using var then have a getter and setter change that variable as you like:

function Filter() {
  var filters = {
    "tip-oglasa":           "",
    "zemlja":               "",
    "grad":                 "",
    "deo-grada":            "",
    "min-kvadrata":         "",
    "max-kvadrata":         "",
    "min-soba":             "",
    "max-soba":             "",
    "min-spratova":         "",
    "max-spratova":         "",
    "min-godina-izgradnje": "",
    "max-godina-izgradnje": ""
  };
  
  this.setFilter = function(filter, value){
  	filters[filter] = value;
  }
  
  this.getFilter = function(){
  	return filters;
  }
}

var filter = new Filter();
console.log(Filter.filters);           // private, shows undefined
console.log(filter.getFilter());       // show filter
filter.setFilter("grad", "foo");       // set grad filter to "foo"
console.log(filter.getFilter());       // shows updated filter

Upvotes: 0

Related Questions