2

I am using short circuit evaluation to set a key in an object. For example:

var obj = {foo : 'bar'}
var obj2 = {}

obj2.somekey = obj.baz || obj.foo //will assign 'bar' to obj2.somekey

The only difference with my code from that above, is that instead of assigning obj.foo if obj.baz doesn't exist, I would like obj.somekey to stay undefined. I tried obj2.somekey = obj.baz ||, but it threw me a syntax error.

Note that null and undefined, as this question suggests, are not actually undefined either.

So is there any way I can do this with short circuit syntax?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Ari
  • 3,489
  • 5
  • 26
  • 47
  • 1
    Just assign it `obj2.somekey = obj.baz`, it'll be `undefined` if it doesn't exist. – elclanrs Feb 11 '14 at 03:37
  • Hi, please kindly look at my small blog about short circuiting and I hope it could help a little: http://js-guru.blogspot.com/2015/08/javascript-short-circuiting.html – Allan Chua Aug 11 '15 at 08:54

2 Answers2

2

It seems like the simplest solution would be:

obj2.somekey = obj.baz;

But if you really want the semantics of the logical operator (i.e. empty string, null, 0, NaN, and false, all evaluate to false and so || returns whatever is on the right), use void:

obj2.somekey = obj.baz || void(0);

Note that in this case the property .somekey will be assigned, but the value assigned to it may be undefined. See Felix Kling's excellent answer for a full explanation. To leave the property .somekey itself undefined simply use:

if ('baz' in obj) obj2.somekey = obj.baz;

Or to leave .somekey undefined even if .baz is falsey, use:

if (obj.baz) obj2.somekey = obj.baz;
Community
  • 1
  • 1
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Cool, this is what I needed. Just to probe a little bit further, is there anything that I could assign to a variable in which it would still throw a reference undefined error? – Ari Feb 11 '14 at 03:41
  • Well if `obj` or `obj2` was undefined (or any other objects used in the expression that aren't terminal), then that would obviously result in an error, but other than that, I can't think of anything. – p.s.w.g Feb 11 '14 at 03:43
  • Ah sorry, I think you misunderstood. I mean, is it possible to assign something similar to void(0) to a variable, where the assignment will complete successfully, but when called in the future the variable will still throw a reference error, as opposed to returning undefined with no error (like void(0) does) – Ari Feb 11 '14 at 03:46
  • @Ari: Accessing an undefined property never throws an error. If you are trying to access a member of the undefined property, e.g. `obj.somkey.somethingelse`, then it will always throw an error, whether the property exists (and has the value `undefined`) or not. – Felix Kling Feb 11 '14 at 03:53
  • @Ari Felix is right. It is always *possible* to assign an undefined value to a variable, and accessing any properties of that value will result in an error. – p.s.w.g Feb 11 '14 at 04:06
  • 1
    why `void(0)` and not just `undefined`? – Bernardo Dal Corno Mar 08 '18 at 19:12
2

I would like obj.somekey to stay undefined.

Just to be clear: There is a difference between a property being undefined (with which I mean "it doesn't exist") and a property having the value undefined. No matter what you do, if you write

obj.somekey = ...;

the property will be created and will turn up in for...in loops for example.

If you really want to create the property only when the other property exists, you have to use an if statement:

if (obj.baz) {
   obj.somekey = obj.baz;
}

or the slightly less readable form***:

obj.baz && (obj.somekey = obj.baz)

Because of short circuiting, the right hand operand will only be evaluated if the left hand operand evaluates to true.


* Personally I advocate against this style, because it uses the AND operator for side effects, and doesn't do anything with the return value. The situations where you have to use this style, because you are forced to use an expression, are probably pretty rare.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Yes, I was in particular asking about this. I was curious if it was possible to do what you did in your last block of code, where obj.somekey continues to not exist, but in a one-liner. – Ari Feb 11 '14 at 03:48
  • Updated my answer, although I don't advocate this style. – Felix Kling Feb 11 '14 at 03:52
  • Ok great. One last question. Would it be bad practice to use the other answer/comment's suggestions that end up in the key being set to undefined? As you stated, this would turn up in 'for in' loops, as well as Object.keys(), which in my eyes, seems messy and open to bugs. Yet, from what I've seen, most people seem to do this. Thoughts? – Ari Feb 11 '14 at 04:04
  • +1 for the explanation about undefined values versus undefined properties. – p.s.w.g Feb 11 '14 at 04:07
  • 1
    @Ari: It really depends on how your code works. If your code is implicitly assuming that every existing property has a "valid" value, you will run into problems if you have undefined ones. If you account for such properties, then you won't. There are pros and cons for both sides, which also depend on the rest of your code. For example, if you are writing a library, i.e. your code is to be used by third party code, I would rather code defensively and take into account that there might be properties with undefined values. Or you don't and explicitly state in the documentation how to do it. – Felix Kling Feb 11 '14 at 04:08