📜 ⬆️ ⬇️

Present and future safe operation with null and undefined in JavaScript

The author of the material, the translation of which we are publishing today, was recently caught by one question on StackOverflow, which made him think about handling null and undefined values ​​in JavaScript. Here he gives an analysis of the current situation, shows some techniques of safe work with null and undefined , and also, speaking about the future, considers the operator ?. .

image

Basic information


Undefined is a primitive value that is automatically assigned to declared, but uninitialized variables. This value can be obtained by referring to a non-existent property of the object or to a non-existent argument of the function.

Null is another primitive value, which is the absence of a value. For example, if the variable is assigned the value null , it can be interpreted as the fact that at this stage of the program’s work this variable exists, but it still has neither type nor value.
')
Let's see what happens if you run this code:

 let obj; console.log(obj.someProp); 

It will give the following error:

 TypeError: Cannot read property 'someProp' of undefined 

Similar things can be seen when trying to work with variables that have a null value.

Check for null and undefined


How to avoid such phenomena? Luckily for us, JavaScript supports the computation of logical expressions using a short circuit (short circuit evaluation). This means that in order to avoid the TypeError error described above, you can write the following code:

 let obj; console.log(obj && obj.someProp); //  undefined 

But what if you need to go deeper, for example, to get to something like obj.prop1.prop2.prop3 ? In this situation, you can try to solve the problem by performing a lot of checks:

 console.log( obj && obj.prop1 && obj.prop1.prop2 && obj.prop1.prop2.prop3 ); 

Although this works, such designs do not look very good.

But what if we need to output some standard value, if undefined or null is found in such a chain? This is possible, but then you will have to write more code:

 const evaluation = obj && obj.prop1 && obj.prop1.prop2 && obj.prop1.prop2.prop3; console.log( evaluation != null ? evaluation : "SomeDefaultValue" ); 

Before we continue thinking about null and undefined in javascript, let's talk about how similar values ​​are processed in other languages.

Other languages


It should be noted that the problem of working with undefined values ​​is present in most programming languages. Let's see how checks are carried out, similar to those described above, in other languages.

▍Java


Java has api Optional :

 SomeClass object; Optional.ofNullable(object)   .map(obj -> obj.prop1)   .map(obj -> obj.prop2)   .map(obj -> obj.prop3)   .orElse("SomeDefaultValue"); 

▍Kotlin


In Kotlin (he, like Java, uses the JVM) there are operators elvis ( ?: And safe-call ( ?. ).

 val object: SomeClass? object?.prop1?.prop2?.prop3 ?: "SomeDefaultValue"; 

▍C #


And finally, in C # there are operators null-condition ( ?. ), And null-coalescing ( ?? ).

 SomeClass object; object?.prop1?.prop2?.prop3 ?? "SomeDefaultValue"; 

How to work with undefined in JS?


After considering the possibilities of working with ambiguous values ​​in other languages, I wondered whether it was possible to safely work with undefined in JavaScript and not write code kilometers. So I started experimenting with regular expressions. I wanted to create a function that would allow secure access to the properties of objects.

 function optionalAccess(obj, path, def) { const propNames = path.replace(/\]|\)/, "").split(/\.|\[|\(/); return propNames.reduce((acc, prop) => acc[prop] || def, obj); } const obj = { items: [{ hello: "Hello" }] }; console.log(optionalAccess(obj, "items[0].hello", "def")); //  Hello console.log(optionalAccess(obj, "items[0].he", "def")); //  def 

After I created this function, I learned about the lodash._get method, which has the same signature:

 _.get(object, path, [defaultValue]) 

However, to be honest, I do not belong to fans of string paths, so I began to look for a way to avoid their use. As a result, I created a solution based on proxies:

 //       function optional(obj, evalFunc, def) { //   const handler = {   //         get: function(target, prop, receiver) {     const res = Reflect.get(...arguments);     //    ,    ,  -       return typeof res === "object" ? proxify(res) : res != null ? res : def;   } }; const proxify = target => {   return new Proxy(target, handler); }; //      return evalFunc(proxify(obj, handler)); } const obj = { items: [{ hello: "Hello" }] }; console.log(optional(obj, target => target.items[0].hello, "def")); // => Hello console.log(optional(obj, target => target.items[0].hell, { a: 1 })); // => { a: 1 } 

The future of safe work with null and undefined in javascript


Now the TC39 has a proposal that allows the use of the following structures:

 obj?.arrayProp?[0]?.someProp?.someFunc?.(); 

For me, it looks very neat. However, this proposal is still at a fairly early stage of agreement, that is, its potential appearance in the language may take some time. But despite this, there is a plug-in for babel, which allows us to use such constructions today.

Results


Values ​​like null and undefined present in programming for a very long time, and nothing indicates that they will disappear soon. Probably, the concept of a null value is the most unloved in programming, but we have the means to ensure safe operation with similar values. With regard to working with null and undefined in JavaScript, you can use several approaches discussed above. In particular, here is the code of the functions proposed by the author of this material. If you are interested in the operator ?. , which is expected to appear in JS, take a look at one of our previous publications , which addresses this issue.

Dear readers! Which of the ways of safe work with null and undefined in JavaScript mentioned in this material do you like the most?

Source: https://habr.com/ru/post/373499/


All Articles