1

This is what I'm trying to achieve. Here is an existing piece of code -

function PartMetaData(dataElement) {
this.metaData = new MetaData(dataElement);

this.getDescription = function () {
    return this.metaData.getElement("data-part-description");
};

this.getLength = function () {
    return this.metaData.getElement("data-part-length");
};

this.getWidth = function () {
    return this.metaData.getElement("data-part-width");
};

this.getHeight = function () {
    return this.metaData.getElement("data-part-height");
};

this.getWeight = function () {
    return this.metaData.getElement("data-part-weight");
};
}

Now look at the relationship between the functionname and the attribute name - this looks a lot like repetitive code that can be avoided. Is that something that can be achieved? Is there a way to allow "any" function call to an object and determine what to do depending on the function name?

for eg something like (the syntax is cooked up, I don't know if something like this exists in Javascript, or any other language for that matter)

function PartMetaData(dataElement){
this.metaData = new MetaData(dataElement);

this.get(name?) = function () {
    return this.metaData.getElement("data-part-" + name.toLower());
}

such that the caller can still call

partMetaData.getDescription();

Any ideas? I know I can change the signature and make it one function, I just want to know if the signature can be kept as is with some JS (black?) magic.. Thanks!

2 Answers 2

3

You can make a helper function that you can use like this to create all those methods.

function PartMetaData(dataElement) {
    this.metaData = new MetaData(dataElement);

    function makeAccessor(o, itemName) {
        var ucase = itemName.substr(0,1).toUpperCase() + itemName.substr(1);
        o["get" + ucase] = function() {
            return this.metaData.getElement("data-part-" + itemName);
        }
    }

    var items = ["description", "weight", "height", "width", "length"];
    for (var i = 0; i < items.length; i++) {
        makeAccessor(this, items[i]);
    }
}

A simpler way of doing this with a slightly different interface would be this:

function PartMetaData(dataElement) {
    this.metaData = new MetaData(dataElement);
    this.getProperty = function(name) {
        return this.metaData.getElement("data-part-" + name);
    }
}

And, you would use it like this:

partMetaData.getProperty("height");
Sign up to request clarification or add additional context in comments.

9 Comments

+1 I like the first option, I am trying to avoid the second one. However, even here, I need to know before-hand what type of calls might come in. Is there a way to not put a constraint like this? (the constraint might be a good thing to avoid exceptions, but still I want to know if there's a way to avoid that).
@RoopeshShenoy - you can add methods on the fly by making the makeAccessor() function a public method and having someone call it before the accessor method is used. But, you can't just have a method without first defining it. Somebody has to define it before it can be used. The 100% dynamic option where nothing has to get defined ahead of time is the getProperty() solution.
looks like so, actually I like the second option more than the first one, but I don't want to change the interface if I can. Legacy code :-( will require lots of refactoring.
Will wait for a while to see if someone has a better answer before accepting this one. Thanks!
@RoopeshShenoy - do both. Add the getProperty() option as the "right" way to do it going forward and for all new code. For legacy code, there should be a definitive list of properties/method names that are used so you can use the first option to pre-define those in order to not break the legacy code.
|
0

Yeah, combinging jfriend's solutions works nicely:

function PartMetaData(dataElement) {
    this.metaData = new MetaData(dataElement);

    this.getProperty = function(name) {
        return this.metaData.getElement("data-part-" + name);
    }

    this.makeAccessor = function(name) {
       this["get" + name.substr(0,1).toUpperCase() + name.substr(1)] =
          function() { return this.getProperty(name); }
    }

    var items = ["description", "weight", "height", "width", "length"];
    for (var i = 0; i < items.length; i++) {
        this.makeAccessor(this, items[i]);
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.