1Cr18Ni9
1Cr18Ni9

Reputation: 1867

how to simplify getter-setter functions

I am trying to make a reusable chart with d3.js. The codes are working, but they are very redundant.

I am trying to simplify the code below:

function myChart(){
    // default properties
    var svgWidth = 1000,
        svgHeight = 250;

    function chart(selection){
       // do something with the previous properties ....
    }

    // define setter-getter functions
    chart.svgWidth = function(_){
        if(!arguments.length) return svgWidth;
        svgWidth = _;
        return chart;
    };
    chart.svgHeight = function(_){
        if(!arguments.length) return svgHeight;
        svgHeight = _;
        return chart;
    };

    return chart;
}

As you can see, all the setter-getter functions are very similar. If there are many properties to be set, say 10, then the setter-getter functions will be stacked very long.

So is anybody able to simplify it?

Upvotes: 1

Views: 380

Answers (2)

Gerardo Furtado
Gerardo Furtado

Reputation: 102198

I believe that this getSet.js function is exactly what you want: https://gist.github.com/gneatgeek/5892586.

According to its creator, it can:

Dynamically create getter/setter functions for D3 components

As link-only answers are not recommended at S.O. (since the link can change or become unreachable) here is a brief explanation.

This is the said function:

function getSet(option, component) {
    return function(_) {
        if (!arguments.length) {
            return this[option];
        }

        this[option] = _;

        return component;
    };
}

Let's see how to use it. First, you'll have store your variables in an object (which is one of the drawbacks of the function, see link above), like this:

var opts = {
    width: 200,
    height: 50,
    color: '#000'
};

After that, you use this for...in loop:

for (var key in opts) {
    chart[key] = getSet(key, chart).bind(opts);
}

That way, you can dynamically generate your setter/getters.

Here is a demo, using the getters:

function getSet(option, component) {
    return function(_) {
        if (!arguments.length) {
            return this[option];
        }

        this[option] = _;

        return component;
    };
}

function chart() {
    // do something
};

var opts = {
    width: 200,
    height: 50,
    color: '#000'
};

for (var key in opts) {
    chart[key] = getSet(key, chart).bind(opts);
}

//using the getters
console.log(chart.height())
console.log(chart.width())
console.log(chart.color())
<script src="https://d3js.org/d3.v4.min.js"></script>

Now let's set some values using the setters and after that get them using the getters:

function getSet(option, component) {
    return function(_) {
        if (!arguments.length) {
            return this[option];
        }

        this[option] = _;

        return component;
    };
}

function chart() {
    // do something
};

var opts = {
    width: 200,
    height: 50,
    color: '#000'
};

for (var key in opts) {
    chart[key] = getSet(key, chart).bind(opts);
}

//using the setters...
chart.width(42)
chart.height(3.14)
chart.color("foo")

//...and then the getters
console.log(chart.width())
console.log(chart.height())
console.log(chart.color())
<script src="https://d3js.org/d3.v4.min.js"></script>

Upvotes: 1

Manu Artero
Manu Artero

Reputation: 10263

KISS: define a defaults object and iterate over it's keys in order to create new properties:

function myChart(){
    // default properties
    var defaults = {
      svgWidth: 1000,
      svgHeight: 250
    }

    function chart(selection){
       // do something with the previous properties ....
    }

    Object.keys(defaults).forEach((key) => {
      chart[key] = function(_) {
        if(!arguments.length) return defaults[key];
        defaults[key] = _;
        return chart;
      };
    });

    return chart;
}

Upvotes: 1

Related Questions