
{"id":2202,"date":"2016-12-31T16:44:14","date_gmt":"2016-12-31T21:44:14","guid":{"rendered":"http:\/\/www.ikriv.com\/blog\/?p=2202"},"modified":"2016-12-31T17:39:02","modified_gmt":"2016-12-31T22:39:02","slug":"javascript-wtf-4-undefined-vs-null","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=2202","title":{"rendered":"JavaScript WTF #4: undefined vs null"},"content":{"rendered":"<p>The forth place in the JavaScript WTF competition goes to the <b>amazingly large number of ways to represent lack of value<\/b>. Most C-like languages have keyword <code>null<\/code> that means &#8220;no value&#8221;. Beside <code>null<\/code>, JavaScript also has <code>undefined<\/code>, apparently meaning &#8220;like, totally no value&#8221;. The actual situation is even more complicated. A variable in JavaScript can be in any of the following states of no-value-ness:<\/p>\n<ol>\n<li>Not declared.<\/li>\n<li>Not initialized or explicitly set to <code>undefined<\/code>.<\/li>\n<li>Explicitly set to <code>null<\/code>.<\/li>\n<li>Temporarily dead (this is not a joke).<\/li>\n<\/ol>\n<p>There is an impressive number of subtle differences between these states.<\/p>\n<h3>Not declared<\/h3>\n<p>In default, non-strict mode, not declared variables are treated as not initialized, and have implicit value of <code>undefined<\/code>. In strict mode, accessing a not declared variable causes a <code>ReferenceError<\/code>, except when used with <code>typeof<\/code>. <\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n'use strict';\r\nconsole.log(typeof notDeclared===&quot;undefined&quot;); \/\/ prints true\r\nconsole.log(notDeclared===undefined);          \/\/ ReferenceError\r\n<\/pre>\n<p>Note that <code>typeof notDeclared<\/code> returns string <code>\"undefined\"<\/code>, which is different from <code>undefined<\/code> value.<\/p>\n<h3>Not initialized<\/h3>\n<p>Declared, but not initialized variables are implicitly assigned a value of <code>undefined<\/code>. There is no way to distinguish between a variable that was never initialized, and a variable that was explicitly set to <code>undefined<\/code>.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar notInitialized;\r\nconsole.log(typeof notInitialized===&quot;undefined&quot;); \/\/ true\r\nconsole.log(notInitialized===undefined);          \/\/ true\r\n<\/pre>\n<h3>Null<\/h3>\n<p>Null is interpreted as pointing to no object. It is different from <code>undefined<\/code> in a number of ways:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar nullVar = null;\r\n\r\nconsole.log(typeof nullVar === &quot;object&quot;); \/\/ true\r\nconsole.log(nullVar === null);            \/\/ true\r\nconsole.log(nullVar === undefined);       \/\/ false\r\nconsole.log(nullVar == undefined);        \/\/ true\r\nconsole.log(1+null);                      \/\/ 1\r\nconsole.log(1+undefined);                 \/\/ NaN\r\n<\/pre>\n<p>An attempt to access any property of <code>null<\/code> or <code>undefined<\/code> leads to <code>ReferenceError<\/code>. One can check for <code>null<\/code> or <code>undefined<\/code> in one shot using equality operator &#8220;==&#8221;:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nif (someVar == null) ... \/\/ true if someVar is undefined or null\r\n<\/pre>\n<p>However, simply writing <code>if (!someVar)<\/code> is not recommended: the condition will be true not only for <code>null<\/code> and <code>undefined<\/code>, but also for <code>false<\/code>, the number <code>0<\/code>, the empty string <code>\"\"<\/code> and <code>Number.NaN<\/code>.<\/p>\n<h3>Dead<\/h3>\n<p>Temporarily dead variables are an addition of EcmaScript6: these are variables declared via <code>let<\/code> or <code>const<\/code> keywords in the lines preceding their declaration:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nfunction foo() {\r\n   \/\/ x is in a &quot;temporarily dead zone&quot; (TDZ) here\r\n   let x; \r\n   \/\/ x has value of undefined here\r\n}\r\n<\/pre>\n<p>&#8220;Normal&#8221; variables are &#8220;hoisted&#8221; to the top of their scope, but &#8220;let&#8221; and &#8220;const&#8221; variables are not. Any access to a <code>let<\/code> or <code>const<\/code> variable prior to its declaration is not allowed. This includes the <code>typeof<\/code> operator.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nconsole.log(declaredLater===undefined);        \/\/ true\r\nconsole.log(typeof notDeclared===&quot;undefined&quot;); \/\/ true\r\nconsole.log(typeof dead);                      \/\/ ReferenceError\r\nvar declaredLater = 42;\r\nlet dead;\r\n<\/pre>\n<h3>Conclusion<\/h3>\n<p>To be fair, there are situations when it helps to distinguish &#8220;a value of null&#8221; and &#8220;no value at all&#8221;. E.g. when sending partial updates, <code>null<\/code> may mean &#8220;replace this field with null&#8221; and <code>undefined<\/code> may mean &#8220;do not touch&#8221;. When dealing with default function parameters: <code>undefined<\/code> means &#8220;use default value&#8221;, and <code>null<\/code> means &#8220;use null&#8221;. In the old days of COM we had VT_NULL, VT_EMPTY, and also vtMissing, which <a href=\"http:\/\/stackoverflow.com\/questions\/1463733\/how-does-com-support-optional-parameters\">actually is a third, different value<\/a>.<\/p>\n<p>Still, JavaScript situation is a mess. The differences between the four &#8220;no-value&#8221; states are not intuitive, to put it mildly, and there are no explicit checks for them. I wish we had something like <code>isDeclared(symbol)<\/code>, and <code>isInTdz(symbol)<\/code>, but alas: the best we can do is to rely on confusing side-effects. Hence, the WTF.<br \/>\n<a href=\"https:\/\/www.codeproject.com\" rel=\"tag\" style=\"display:none\">CodeProject<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The forth place in the JavaScript WTF competition goes to the amazingly large number of ways to represent lack of value. Most C-like languages have keyword null that means &#8220;no <a href=\"https:\/\/ikriv.com\/blog\/?p=2202\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[4,15],"tags":[],"class_list":["entry","author-ikriv","post-2202","post","type-post","status-publish","format-standard","category-hack","category-webdev"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2202","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2202"}],"version-history":[{"count":31,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2202\/revisions"}],"predecessor-version":[{"id":2233,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2202\/revisions\/2233"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}