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

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.