0

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.

2 Answers 2

1

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.
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks! I'm using this in script for my web page so I want to just make whole thing more organized and easier to track / debug without defining data in global space (last project I worked on contained big mess of variables all over the place so I don't want to repeat the same mistake). If I understood you correctly, you think I should make another variable identical to filters in both returned methods and return it instead of filters variable, right?
@Nikola If you are not guarding access at all, you should just use a data object (like filters) directly instead of hiding it behind another object that provides no benefit.
@chdowie, Well, I actually plan to add more functionality (beside others sending this object via AJAX) and make it easier to do instead of changing variable and then calling separate function to send it.
@Nikola Right. So to address your question about "making another variable identical to filters", you can make a shallow clone with return Object.assign({}, filters);. Note that this only copies the top level -- if any of the values of your filters object are also objects (or arrays, or generally anything non-primitive) then you need to do a deep clone instead. This can potentially be costly to do all of this duplication.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.