5

I've often used the following pattern in my Javascript:

x = couldBeNullThing || valueIfItIsNull;

because it beats than:

x = couldBeNullThing ? couldBeNullThing : valueIfItIsNull;

I also frequently use a slight variant of that same pattern:

x = x || valueIfXIsNotDefined;

That's all great ... except the problem is, I recently discovered:

foo = "";
//assert foo.x === undefined;
foo.x = foo.x || valueIfXIsNotDefined;
//assert foo.x === undefined;

In other words, if you have a string, and you do string.aPropertyThatStringDoesntHave || foo, you'll get back neither foo nor an actual value; instead you get undefined.

Can anyone explain why this is? It seems to me that if foo.x is undefined, then foo.x || anythingElse should always result in anythingElse ... so why doesn't it?

machineghost
  • 33,529
  • 30
  • 159
  • 234
  • Interestingly, it seems to work if you do `foo = new String("")` – Gohn67 Mar 24 '12 at 02:17
  • Another thing I noticed, is that using `console.log(foo)` returns "(an empty string)", and when using new String("") it returns a String object. Also, I'm on Firefox. May be different on other browsers. – Gohn67 Mar 24 '12 at 02:20
  • Ugh sorry for spamming. But it's an interesting question. Also `foo = String("")` returns "(an empty string"). And additionally doing something like `foo = "Test".substr(1)` returns just a string value and not an object. – Gohn67 Mar 24 '12 at 02:24
  • Anyway this may answer your question: http://stackoverflow.com/questions/2051833/difference-between-the-javascript-string-type-and-string-object – Gohn67 Mar 24 '12 at 02:26
  • For an empty string `s`, `s.no_such_property` gives me `undefined` as expected and `s.no_such_property || 11` gives me `11` as expected. I get the same (expected) results in Firefox, Chrome, and Safari. What am I supposed to be seeing? Am I looking at the wrong thing? http://jsfiddle.net/ambiguous/8wwUh/ – mu is too short Mar 24 '12 at 02:34
  • ^I think it has to do with his pattern of `x = x || valueIfXIsNotDefined`. So if you do `foo.x = foo.x || valueIfXIsNotDefined` and then do `console.log(foo.x)` you will get undefined. I think this is because foo is just a plain string literal and not an object. – Gohn67 Mar 24 '12 at 02:42
  • Works as expected for me: http://jsfiddle.net/xxLtP/1/ – gilly3 Mar 24 '12 at 02:42

1 Answers1

2

While I'm familiar with the concept of assert I wasn't aware that JavaScript had that functionality. So with that in mind I could be completely wrong but it seems to me that this statement:

assert (foo.x || valueIfXIsNotDefined) === undefined;

...is calling a function called assert(), passing it the parameter foo.x || valueIfXIsNotDefined and then comparing the return value from the assert() function with undefined. Perhaps what you need is this:

assert(foo.x || valueIfXIsNotDefined === undefined);

If I try something similar with console.log():

var foo = "",
    valueIfXIsNotDefined = "test";
console.log( foo.x === undefined);
console.log(foo.x || valueIfXIsNotDefined === undefined);

​Then it logs:

true
false

Similarly, after:

var result = foo.x || valueIfXIsNotDefined;

result is "test".

http://jsfiddle.net/YBPyw/

Further, if you actually try to assign foo.x equal to something (where foo was a string) it doesn't work, so when you later test foo.x it will give undefined.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • Sorry, you are correct that JS doesn't have a native assert. I was just trying to explain the situation, but I really should have said "// assert .." to be clearer (I'll edit the question). Your final sentence answered my question (thanks), but it took the comments from Gohn67 to understand it. For other readers, as I understand it the reason var foo = ""; foo.x = 1; foo.x != 1; is because in the second statement foo gets temporarily converted in to new String(foo). This allows it to get an x property assigned to it, but then afterward it goes back to being a (property-less) primitive. – machineghost Mar 24 '12 at 19:15