31

I love those short js oneliners. I'd like to know if there's something logical and elegant for:

  • intializing a variable to zero if undefined
  • increment by one otherwise.

Shorter than this preferrably ;)

var obj = {} ; 

//some iterative called function
obj.prop = obj.prop===undefined?0:obj.prop++;
1

6 Answers 6

52

This will result in NaN for the first increment, which will default to 0.

obj.prop = ++obj.prop || 0;
Sign up to request clarification or add additional context in comments.

11 Comments

Sweet. NAN results in falsy thus the second argument of the lazy-OR is executed. Waiting a minute for some other answers otherwise accepting this.
@chumkiu: I don't know what you mean. It works with the code in the question.
@chumkiu yes, because referencing an undeclared variable is an error. It works if you declare using the var keyword first, though - var a = ++a || 0.
@Alnitak: Do you mean an undeclared variable? It'll work just fine for variables that are declared but have an undefined value. ...Nevermind, just saw your updated comment.
@user1689607 yes but it doesn't works with simple a variable. The answer say about variable (generic). Though the example is a property of object
|
47

A cleaner way of doing this is simply

obj.prop = obj.prop + 1 || 0;

Using the increment operator is wrong or overkill. The suffixed operator, x++, (the example in the question) should not work at all. The prefixed, ++x, leads to assigning twice (like saying x = x = x+1)

2 Comments

Just out of curiosity, why does it hurt to assign twice?
@CharlesWood Late comment, but you'll be instantly doubling your runtime. Considering these increment or set to zero lines are generally used in for loops, it's a prime spot for optimisation if 'n' is high, especially if said optimisation also increases ease of reading. (Edit: On further thought, it might be the case that this gets optimised out by the interpreter, but I wouldn't bet on it.)
5

This works for both plain JS and TypeScript:

obj.prop = (obj.prop ?? 0) + 1;

2 Comments

(obj.prop ?? 0) + 1 initializes to 1 not 0
I understood that to be desired. This can be trivially altered in to (obj.prop ?? -1) + 1 ofc.
3

To initialise to 1 obj.prop = -~obj.prop

To initialize to 0 ~~++obj.prop OR ++obj.prop | 0

2 Comments

wow, nice approach! But: 1. it's a brainf*ck to read :) and 2. it's not correct, it initialises to 1, not 0
Ha yes that's right, so the shorter i can make is obj.prop = ~~++obj.prop that is the same as ++obj.prop | 0 where | 0 is like math.floor
2

Similar to I Hate Lazy's answer but avoids the double assignment as Bodgan points out

++obj.prop || (obj.prop=0)

in the global scope

++window.foo || (window.foo=0)

Comments

1

It is not possible to directly pass a variable to the function inc(obj.prop), because in javascript variables are passed by value, but you can pass the object itself and the name of the variable you want to increment.

Object.prototype.inc = function(n){ this[n]? this[n]++ : this[n] = 1; }

let obj = {};

obj.inc("prop");

// obj.prop == 1

You can also add the required fields to the object before

Object.prototype.has_fields = function(obj2){
    for(let p of Object.keys(obj2)){
        if(obj2[p].constructor == Object){
            if(!this[p]) this[p] = {};
            this[p].has_fields(obj2[p]);
        }else{
            if(!this[p]) this[p] = obj2[p];
        }
    }
    return this;
}

let obj = {};

    obj.has_fields({a:{b:{c:{d:{prop:0}}}}});
    obj.a.b.c.d.prop++;
    // obj.a.b.c.d.prop == 1

    obj.has_fields({a:{b:{c:{d:{prop:0}}}}});
    obj.a.b.c.d.prop++;
    // obj.a.b.c.d.prop == 2

2 Comments

It's better to write your answer in English.
write answer in English

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.