{"id":7575,"date":"2020-03-10T10:37:14","date_gmt":"2020-03-10T14:37:14","guid":{"rendered":"http:\/\/www.ericfeminella.com\/blog\/?p=7575"},"modified":"2024-03-27T00:46:23","modified_gmt":"2024-03-27T04:46:23","slug":"es2020-optional-chaining-nullish-coalescing","status":"publish","type":"post","link":"https:\/\/www.ericfeminella.com\/blog\/2020\/03\/10\/es2020-optional-chaining-nullish-coalescing\/","title":{"rendered":"ES2020 Optional Chaining &#038; Nullish Coalescing"},"content":{"rendered":"<p><img decoding=\"async\" src=\"\/img\/articles\/optional-chaining.png\"\/><\/p>\n<p>Of the various <a href=\"https:\/\/github.com\/tc39\/proposals\" rel=\"noopener noreferrer\" target=\"_blank\">Features proposed<\/a> in <a href=\"https:\/\/tc39.es\/ecma262\/\" rel=\"noopener noreferrer\" target=\"_blank\">ES2020<\/a>, perhaps two of the simplest features will prove to be the most useful, at least in terms of simplification and maintenance are concerned.<\/p>\n<p>Specifically, the <a href=\"https:\/\/github.com\/tc39\/proposal-optional-chaining\" rel=\"noopener noreferrer\" target=\"_blank\">Optional Chaining Operator<\/a> and <a href=\"https:\/\/github.com\/tc39\/proposal-nullish-coalescing\" rel=\"noopener noreferrer\" target=\"_blank\">Nullish Coalescing Operator<\/a> are of particular interest as they are certain to result in less verbose, less error prone expressions. <\/p>\n<h2 id=\"optional-chaining\" class=\"section-link\">\n <a href=\"#optional-chaining\">Optional Chaining<\/a><br \/>\n<\/h2>\n<p>In a nutshell, Optional Chaining provides a syntax for <code>undefined \/ null<\/code> checks when performing nested object references using a simple question mark appended by a dot (<code>?.<\/code>) notation.<\/p>\n<p>For instance, consider how many times you may have written defensive expressions similar to the following:<\/p>\n<pre class=\"lang:js\" >\nconst roleName = (\n  user && user.role && user.role.name\n);\n\n\/\/ or provide a default value ...\nconst roleName = (\n  user && user.role && user.role.name || ''\n);\n\/\/ or ...\nconst roleName = (\n  user && user.role ? user.role.name : ''\n);\n<\/pre>\n<p>Or perhaps you have assigned intermediate values to temporary variables to perform the same:<\/p>\n<pre class=\"lang:js >\nconst role = user && user.role;\nconst isAdmin = Boolean(role && role.isAdmin);\nconst roleName = role && role.name;\n<\/pre>\n<p>The need to check for possible reference errors quickly becomes tedious, and with each lookup we increase the potential for introducing bugs. Utilities can be implemented for delegating these checks, but ultimately, this just moves the problem from one context to another, resulting in additional\u00a0points for failure.<\/p>\n<p>With Optional Chaining, however, accessing properties safely becomes considerably less verbose, as the examples above can be simplified to:<\/p>\n<pre class=\"lang:js >\nconst isAdmin = Boolean(user?.role?.isAdmin);\nconst roleName = user?.role?.name;\n<\/pre>\n<p>Reference checks when invoking functions also become simplified:<\/p>\n<pre class=\"lang:js decode:true\" >\nconst permissions = user?.role?.getPermissions();\n<\/pre>\n<p>And dynamic property references can safely be performed as well:<\/p>\n<pre class=\"lang:js decode:true \" >\nconst id = user?.['role']?.id;\n<\/pre>\n<h2 id=\"nullish-coalescing\" class=\"section-link\">\n <a href=\"#nullish-coalescing\">Nullish Coalescing<\/a><br \/>\n<\/h2>\n<p>In addition, combined with the <a href=\"https:\/\/github.com\/tc39\/proposal-nullish-coalescing\" rel=\"noopener noreferrer\" target=\"_blank\">Nullish Coalescing Operator<\/a>, Optional Chaining becomes even more succinct as one can specify a value to resolve to rather than the default (<code>undefined<\/code>) by simply using a double question mark (<code>??<\/code>) notation. For example:<\/p>\n<pre class=\"lang:js decode:true\" >\n\/\/ assign an empty string as default ...\nconst roleName = user?.role?.name ?? \u2018\u2019;\n\/\/ and ...\nconst permissions = user?.role?.getPermissions() ?? [];\n<\/pre>\n<p>Moreover, Nullish Coalescing, while intended as a compliment\u00a0to Optional Chaining, also solves additional problems when dealing with falsy values. For instance, consider how many times you may have written something similar to the following:<\/p>\n<pre class=\"lang:js decode:true\" >\n\/\/ assuming zero is valid, will incorrectly default to 500 ...\nconst refreshRate = preferences.refreshRate || 500;\n\/\/ or perhaps ...\nconst refreshRate = _.isNumber(preferences.refreshRate) ? preferences.refreshRate : 500;\n<\/pre>\n<p>With the Nullish Coalescing Operator, we can avoid the problems outlined above as only <code>undefined<\/code> and <code>null<\/code> values will evaluate to true, so falsy values are safe:<\/p>\n<pre class=\"lang:js decode:true\" >\n\/\/ assuming refreshRate is zero, will correctly assign 0 ...\nconst refreshRate = preferences.refreshRate ?? 500; \/\/ 0\n<\/pre>\n<p>Since Nullish Coalescing only checks for <code>undefined<\/code> and <code>null<\/code>, the above holds true for all other falsy values, so <code>false<\/code>, empty <code>strings<\/code>, and <code>NaN<\/code> are safe as well..<\/p>\n<h2 id=\"optional-chaining-destructuring\" class=\"section-link\">\n <a href=\"#optional-chaining-destructuring\">Optional Chaining w\/Destructuring<\/a><br \/>\n<\/h2>\n<p>One thing to note is that Optional Chaining does not resolve when destructuring. So, for example, the following will throw an exception:<\/p>\n<pre class=\"lang:js decode:true\" >\nconst {someProp} = user?.role?.['test'];\n\/\/ TypeError: Cannot destructure property 'someProp' of '(intermediate value)' as it is undefined.\n<\/pre>\n<p>Interestingly, though, combined with Nullish Coalescing, an exception will not be raised; though, the default will not be assigned, either:<\/p>\n<pre class=\"lang:js decode:true\">\nconst {someOtherProp} = user?.role?.['test'] ?? false;\n\/\/ undefined\n<\/pre>\n<h2 id=\"conclusion\" class=\"section-link\">\n  <a href=\"#conclusion\">Concluding Thoughts<\/a><br \/>\n<\/h2>\n<p>As can be seen, <a href=\"https:\/\/tc39.es\/ecma262\/\" rel=\"noopener noreferrer\" target=\"_blank\">ES2020<\/a> has no shortage of new features on offer to be excited about and, while arguably not as exciting as other features, <a href=\"https:\/\/github.com\/tc39\/proposal-optional-chaining\" rel=\"noopener noreferrer\" target=\"_blank\">Optional Chaining<\/a> combined with <a href=\"https:\/\/github.com\/tc39\/proposal-nullish-coalescing\" rel=\"noopener noreferrer\" target=\"_blank\">Nullish Coalescing<\/a> will certainly prove to be valuable additions.<\/p>\n<p>Both Optional Chaining and Nullish Coalescing proposals are currently at Stage 4 and are available in most modern browsers as well as via the following <code>babel<\/code> plugins: <a href=\"https:\/\/babeljs.io\/docs\/en\/babel-plugin-proposal-optional-chaining\" rel=\"noopener noreferrer\" target=\"_blank\">@babel\/plugin-proposal-optional-chaining<\/a> and <a href=\"https:\/\/babeljs.io\/docs\/en\/babel-plugin-proposal-nullish-coalescing-operator\" rel=\"noopener noreferrer\" target=\"_blank\">@babel\/plugin-proposal-nullish-coalescing-operator<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Of the various Features proposed in ES2020, perhaps two of the simplest features will prove to be the most useful, at least in terms of simplification and maintenance are concerned. Specifically, the Optional Chaining Operator and Nullish Coalescing Operator are of particular interest as they are certain to result in less verbose, less error prone expressions. Optional Chaining In a&#8230; <a class=\"read-more\" href=\"https:\/\/www.ericfeminella.com\/blog\/2020\/03\/10\/es2020-optional-chaining-nullish-coalescing\/\">Continue Reading<\/a><\/p>\n","protected":false},"author":1,"featured_media":8579,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[133,246,78,35],"tags":[264,312,68,315,316,313,314,317],"class_list":["post-7575","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-browsers","category-es6","category-javascript-2","category-software-engineering","tag-babel","tag-es2020","tag-javascript","tag-nullish-coalescing","tag-nullish-coalescing-operator","tag-optional-chaining","tag-optional-chaining-operator","tag-stage-4"],"jetpack_publicize_connections":[],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.ericfeminella.com\/blog\/wp-content\/uploads\/2020\/03\/optional-chaining.png?fit=718%2C320&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/posts\/7575","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/comments?post=7575"}],"version-history":[{"count":1,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/posts\/7575\/revisions"}],"predecessor-version":[{"id":8563,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/posts\/7575\/revisions\/8563"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/media\/8579"}],"wp:attachment":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/media?parent=7575"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/categories?post=7575"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/tags?post=7575"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}