1

I have feeling this must be a duplicate, but I've been unable to find anything, probably due to different wording, or just because there really is nothing better.

I am generating kind of huge chunk of JS code, which "ORs" object properties with variables, while identifiers don't necessarily match. It looks like this (values are boolean):

a.borderline = a.borderline || borderline;
a.st1 = a.st1 || st;
a.ref64 = a.ref64 || ref;
a.unfortunatelySometimesQuiteLongIndentifier123 = a.unfortunatelySometimesQuiteLongIndentifier123 || unfortunatelySometimesQuiteLongIndentifier;
...

To make it leaner I tried something like

a.st1 |= st;

but it makes a.st1 integer instead of boolean and I don't want to add another line with double negation to retype it back to boolean.

Using intuition I also tried ||=, which did not help :)

Is there any better (shorter) way of writing these commands?

Note: I cannot process the commands using a loop, because the commands are not executed all at once, instead they are spread in small chunks in the rest of the code (which was omitted for simplicity).

Erlik
  • 658
  • 8
  • 24
  • 2
    In Javascript, no, not that I know of. You may want to look into coffeescript, which has a `?=`. – James Duffy Apr 30 '14 at 16:57
  • Is there a specific reason why `1` and `0` are objectionable? – Patrick Q Apr 30 '14 at 16:59
  • @PatrickQ Later I am making JSON out of it and sending it somewhere. To comply with the protocol I have to distinguish between `0` and `false`. Yet I cannot convert all zeroes to `false`, as there are also valid numeric values. – Erlik Apr 30 '14 at 17:39

2 Answers2

3

No, there is no shorthand OR operator in javascript. Coffeescript however does provide ||= and ?= to support this idiom.

Is there any better (shorter) way of writing these commands?

In your case, you're amending the a object instead of assigning to variables. You might do this in a loop fashion:

function amendWith(target, source)
    for (var p in source)
        if (!target[p])
            target[p] = source[p];
    return target;
}

amendWith(a, {
    borderline: borderline,
    st1: st,
    ref64: ref,
    unfortunatelySometimesQuiteLongIndentifier123: unfortunatelySometimesQuiteLongIndentifier
    …
});
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Unfortunately, I can't use the loop (added the **Note** after you had probably read the question), but I'll definitely investigate Coffeescript option. Thanks! – Erlik Apr 30 '14 at 17:42
  • Yeah, I didn't notice the edit. You might however post your full code (either in a new question at [cr.SE], in some paste service online, or into your question) so that we can see whether there is a better pattern then. – Bergi Apr 30 '14 at 17:55
  • OK, cool! Coffeescript will work for me. Luckily, it can be compiled into the "long" code after passing the bottleneck, so CS saves the day. Btw interestingly, the `a.st1 ||= st` is compiled into `a.st1 || (a.st1 = st);`, which took me a while to understand, but well.. it works :) – Erlik Apr 30 '14 at 18:15
1

I'm not sure this is any shorter, but just as an alternative idea you could put the OR logic in a function and then loop through your values.

function myFunctionName(value1, value2) {
  return value1 || value2;
}

//names are property names of object 'a' that you want to set, values are the alternate (default) values
var myMapping = {borderline:borderline, st1:st, reallyLongName123:reallyLongName}; 

for (temp in myMapping) {
  a.temp = myFunctionName(a[temp], myMapping[temp]);
}

Since your unable to use a loop and you don't know all the values ahead of time, you could try adding the function to your object 'a'

a.test = function(propName, otherValue) {
  this[propName] = this[propName] || otherValue;
};

a.test("borderline", borderline);
Mike
  • 2,399
  • 1
  • 20
  • 26
  • 1
    Not shorter since you're *still* repeating `a.borderline` twice. – Mike Christensen Apr 30 '14 at 17:19
  • Exactly, the main problem is repeating of the `a.borderline` part, which can sometimes be very long. – Erlik Apr 30 '14 at 17:40
  • @Erlik I updated the code to use a loop, does that make it any cleaner? – Mike Apr 30 '14 at 17:43
  • @monkybonk05 Yes, now it's not repeated. However, I cannot use loop, neither the static initialization `var myMapping = {...`. I am obtaining the values in a scattered way as well as using them (see the **Note** later added to my question). – Erlik Apr 30 '14 at 17:46
  • 1
    @Erlik Are you able to add functions to object 'a'? If so, check out my update. – Mike Apr 30 '14 at 18:08
  • @monkybonk05 That's actually very interesting and yet so simple. `a` is not the only object changed this way, but I can modify it to `test = function(a, propName, otherValue) {...` Thanks! +1 – Erlik Apr 30 '14 at 18:21