10

In JavaScript undefined can be reassigned, so it is often advised to create a self executing function that assures undefined is actually undefined. As an alternative null and undefined are definitely == but are any other values loosely equivalent to null/undefined?

TLDR

Basically can you safely replace this:

(function(undefined){

   window.f = function(obj){
     if(obj===undefined || obj===null ){
       alert('value is undefined or null');
     }
   }

})();

with:

window.f = function(obj){
  if(obj==null){
    alert('value is undefined or null');
  }
}

If the above is 100% safe, why doesn't the JavaScript community/libraries drop undefined altogether and use the shorter x == null conditional to check for both null/undefined at once?

EDIT:

I have never seen someone actually represent an "unknown value" with 'undefined' vs null? I have never seen this scenario, and is why I originally asked the question. It just appears to be two incredibly confused values that are never used in their original intent. Standardizing everything to do a comparison obj==null would be beneficial for size and avoid any issues with reassignment. Everything would continue to work

var obj={};
obj.nonExistantProperty==null // true

var x;
ix==null // true

function(obj){
  obj==null // true
}

The one exception to this rule appears to be when casting undefined/null to an integer. This is a pretty age case scenario, but definitely should be noted.

+(null)==0 while isNaN(+undefined)

Considering NaN is the only value in JavaScript not equal to itself, you can do some pretty crazy things like:

+undefined == +undefined // false
+null == +null // true

Using null as a loose equality == drop in replacement for undefined is safe, provided you don't plan to cast the value to an integer. Which is a pretty edge case scenario.

Lime
  • 13,400
  • 11
  • 56
  • 88

4 Answers4

6

The abstract equality algorithm from section 11.9.3 of the language spec is what defined == and != and it defines them such that

null == void 0
null == null
void 0 == null

where void 0 is just a reliable way of saying undefined (see below) so the answer to your question is yes, null is equal to undefined and itself and nothing else.

The relevant parts of the spec are

1. If Type(x) is the same as Type(y), then
     If Type(x) is Undefined, return true.
     If Type(x) is Null, return true.
     ...
2. If x is null and y is undefined, return true.
3. If x is undefined and y is null, return true.
...

If you're worried about undefined meaning something other than what it normally means, use void 0 instead.

null               ==  void 0           // True
({}).x             === void 0           // True
"undefined"        === typeof void 0    // True
(function () {})() === void 0           // True
(undefined = 42,
 undefined         === void 0)          // False
"undefined"        === typeof undefined // False
"undefined"        === typeof void 0    // True

From the language specification:

11.4.2 The void Operator

The production UnaryExpression : void UnaryExpression is evaluated as follows:

  1. Let expr be the result of evaluating UnaryExpression/.
  2. Call GetValue(expr).
  3. Return undefined.

So the void prefix operator evaluates its argument and returns the special value undefined regardless of to what the global variable undefined has been changed (or whether undefined is defined :).

EDIT: In response to comments,

If you are dealing with library code that distinguishes between the two, then you need to deal with the difference. Some of the new libraries standardized by the language committee do ignore the difference : JSON.stringify([void 0]) === "[null]" but there is too much code out there that treats them subtly differently, and there are other differences :

+(null) === 0
isNaN(+undefined)

"" + null === "null"
"" + undefined === "undefined"

If you're writing any kinds of libraries that produce text or serialize/deserialize and you want to conflate the two then you can't pass undefined through and expect it to behave as null -- you need to explicitly normalize your inputs to one or the other.

Community
  • 1
  • 1
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • You could just as easily use `null` in the code above as using `void 0`. I could also argue that `null` is slightly easier to read and type then `void 0`. My point is there appears to be no value in distinguishing between the two. Although undefined is supposed to represent an "unkown value", nobody actually holds to this convention. So it would appear beneficial to ignore `undefined` every existed and just use `obj==null` in its place. – Lime Jul 26 '11 at 17:54
  • Thanks, I wasn't aware of what the values were when casted to integers. Having `NaN` vs `0` is definitely different. It appears `[null].join('')` and `[undefined].join('')` are equivalent though. – Lime Jul 26 '11 at 18:13
4

Because JavaScript has both values. And while other languages may only have nil/null JavaScript grew up with undefined being the "unknown value" while null is clearly a known value to represent nothing.

Compare var x where x is undefined because no value has been assigned and var y = null where y is null. It was set to something -- a sentential representing "nothing". This core fundamental usage of undefined vs null in JavaScript runs very deep and other cases include:

  1. A missing (or delete'd) property also yield undefined and not null (it would result in null only if null had been assigned).
  2. Unassigned function parameters are undefined.
  3. undefined returned from standard functions like getElementById. See comments.

Thus, in Javascript, it is often more correct to use undefined and not null. They both represent different things. A library that tries to fight this is fighting JavaScript.

Happy coding.


Personally, in almost all cases I avoid an explicit check for undefined or null. I believe that in most -- but not all -- cases all false values should be equivalent and that it is the callers responsibility to conform to the public contract stated.

Because of this belief I would consider the comparison x == null on the verge of trying to guard too much and yet too little, but in the case of catching null or undefined, it works, as pointed out. Go start a trend ;-)

  • 1
    DOM methods such as `getElementById` return `null` because the notion of `undefined` is not present in the [WebIDL](http://www.w3.org/TR/WebIDL/), there's a `void` type in the spec but it's used just for operations that yield no value. – Christian C. Salvadó Jul 26 '11 at 17:45
  • Good answer, would also add: `delete` produces a different result (`undefined`) than `= null`. – Nicole Jul 26 '11 at 17:45
  • How often do people actually intentionally represent an "unknown value" with `undefined`? I have never seen this scenario, and is why I originally asked the question. It just appears to be two incredibly confused values that are never used in their original intent. Standardizing everything to do a comparison `obj==null` would be beneficial for size and avoid any issues with reassignment. Everything would continue to work `var obj={};obj.nonExistantProperty==null`. `var x;if(x==null);` – Lime Jul 26 '11 at 17:49
  • @Lime My answer focus on meaning, not the use in a guard. Except in cases *where* `null` was given a special meaning, `x == null` would catch when it was `undefined` (the likely case) and when it was `null` without harm. However, I would consider `null` being passed to a function either 1) A normal falsey value 2) A special sentinel value, depending upon the function contract. As you point out, however, the conditional check does catch both, so if both cases are expected to be caught, it has the same semantics. –  Jul 26 '11 at 17:53
  • @CMS Doh. Brain melt today. Corrected. –  Jul 26 '11 at 17:55
  • 1
    @pst It would be great to see some production code where distinguishing between `undefined` and `null` for a variable/property is valuable for readability and functionality because it appears to add ongoing confusion. – Lime Jul 26 '11 at 18:00
2

Because of this:

var myVar1;
var myVar2 = null;

if (myVar1 === null) alert('myVar1 is null');
if (myVar1 === undefined) alert('myVar1 is undefined');
if (myVar2 === null) alert('myVar2 is null');
if (myVar2 === undefined) alert('myVar2 is undefined');

Anything set to null is not undefined - it's defined as null.

Brian
  • 2,772
  • 15
  • 12
  • My point is there appears to be no value in distinguishing between the two. Although `undefined` is supposed to represent an "unkown value", nobody actually holds to this convention. – Lime Jul 26 '11 at 17:44
  • Assuming you never assign anything to a value of undefined, there's value in being able to differentiate between an untouched variable and a nullified one. Though, for all pratical purposes in how JS is used by developers today, I can see your point... – Brian Jul 26 '11 at 17:47
0

Reading Javascript: The Good parts, it seems that only null and undefined are equivalent

JavaScript has two sets of equality operators: === and !==, and their evil twins == and !=. The good ones work the way you would expect. If the two operands are of the same type and have the same value, then === produces true and !== produces false. The evil twins do the right thing when the operands are of the same type, but if they are of different types, they attempt to coerce the values. The rules by which they do that are complicated and unmemorable. These are some of the interesting cases:

'' == '0' // false
0 == '' // true
0 == '0' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true

"JavaScript: The Good Parts by Douglas Crockford. Copyright 2008 Yahoo! Inc., 978-0-596-51774-8."

Timo Tijhof
  • 10,032
  • 6
  • 34
  • 48
user278064
  • 9,982
  • 1
  • 33
  • 46