tags:

views:

237

answers:

8

Alright, I find the code below to be quite repetitive and annoying. Any other way to refactor the code without using an array as a starting point (that is, to avoid using array[x], array[y], array[z] later on in the code as a result of starting with an array because x,y,z are completely unrelated and it makes no sense to group them for the sake of readability)

var x = "";
var y = "";
var z = "";
...

...variables get set

if(x != undefined && x != "")
    doSomethingHere();

if(y != undefined && y != "")
    doSomethingThere();

if(z != undefined && z != "")
    doSomethingElse();
...
+1  A: 

Is there a reason you initialize x,y and z to "" ?

If you just do

 var x;

 ..... maybe set x .....

 if (x)
    doSomething()

You save quite a lot of fuzz. You can do the same for y and z ;) The initial value of x is undefined, which you can check with if (x), which means the same as if (x != undefined)

krosenvold
Actually, in javascript any of the following values will evaluate as false in a conditional: false, null, undefined, "", 0, NAN.
JacobM
.... and therefore (adding to what JacobM said) the statement you wrote is not equivalent to the one in the question
Newbie
@Newbie you're right. I still think you should rework the intermediate setting logic so that my code becomes your code ;) There's something about the "rule of least-surprise" which I feel you're violating.
krosenvold
A: 

I'm guessing the original should have used y != undefined and doSomething () is the same function in all cases:

if((x != undefined && x != "") || 
   (y != undefined && y != "") ||
   (z != undefined && z != ""))
    doSomething();
SAMills
+1  A: 

First of all, because both undefined and the empty string ("") evaluate as "false" in javascript, you can change your conditionals to:

if (x) 
     doSomething();
if (y) 
     doSomething();
if (z) 
     doSomething();

If the Something to be Done is always the same, you can certainly do

if (x || Y || z)
     doSomething();
JacobM
but if x,y,z, equal to 0 then you example wont work, it will not give the same results as the example provided in the question
Newbie
Fair point. We're assuming a particular type of value (which of course we can't be guaranteed in Javascript). We assume all of the values are strings; it will work properly if assigned to "0", just not to 0.
JacobM
Similarly, your original code would ignore Null or NaN, which might not be what you want.
JacobM
You are 100% right. I think Joel Coehoorn's, below, solution is the best fit for the problem. Do you agree?
Newbie
It depends. The cleanest solution might be to try to match up your particular needs with the way javascript defines "truthiness" -- but that might not be possible. If the conditional is complicated or likely to change, than abstracting it into a boolean function is definitely a good approach.
JacobM
+7  A: 

At very least you can factor out your validation rules to their own function:

function IsValid(x)
{
    return (x != undefined && x != "");
}

var x = "";
var y = "";
var z = "";
//...

//...variables get set

if(IsValid(x)) doSomething();
if(IsValid(y)) doSomething();
if(IsValid(z)) doSomething();
Joel Coehoorn
Take that one step more and let the IsValid accept a func and do the "if" check in there. IfIsValid(x,doSomethingHere);IfIsValid(y,doSomethingThere);
Mark
:( no preservation of formatting in comments.
Mark
A: 

So to follow up on krosenvold's answer I think what you want is

var x;
var y;
var z;

// do stuff

if (x||y||z)
  doSomething();

Which is much neater

DanSingerman
what you wrote is very different from the example in the question, for example, what if x, y, or z are equal to 0? Then your if returns false
Newbie
+2  A: 

If you're trying to avoid repetition, be it vertical (var x;\r\n;var y;\r\n...) or horizontal (if (x || y || z || ...), a nice way to tidy things up is to gather your variables into an object as properties:

var vars = {
    x: 42,
    y: "",
    z: undefined
};

for (var v in vars) {
    var value = vars[v];

    if (value != undefined && value != "") {
        doSomething();
    }
}

On top of that, if the action to be taken is different for each variable, you can also define an "actions" structure:

var actions = {
    x: doSomething,
    y: doSomethingElse,
    z: doSomething
};

for (var v in vars) {
    var value = vars[v];

    if (value != undefined && value != "") {
        actions[v]();
    }
}
Ates Goral
+7  A: 

In addition to what joel said you could also do the following:

function doOnValid(x, func){
 if(x != undefined && x != "") func();
}

Then you could do:

doOnValid(x, doSomething);
doOnValid(y, doSomethingElse);
doOnvalid(z, function() { /*Yay lambda function*/ });
Pim Jager
you forgot to change the x in the function to var. ;)
Leonel Martins
+1 anyway for the func parameter.
Leonel Martins
Ah thanks, I'll fix it.
Pim Jager
Whoops. should of read down a bit more before suggesting this on Joel's.
Mark
You should probably change the name of "isValid" to something else, it's not returning a bool.
Luca Matteis
Your right, I copied Joels function and edited it. I'll rename to: DoOnValid() (I'm not very good at function naming.)
Pim Jager
A: 

This is about as concise as I can make it, assuming you want a unique action for each condition.

(x && doX());
(y && doY());
(z && doZ());

This works because your particular variable test just reduces to the value of the variable. You can, of course, also write a custom condition function:

function is_valid(x){
    // return true or false
}

( is_valid(x) && doX() );
( is_valid(y) && doY() );
( is_valid(z) && doZ() );
Triptych