By Dmitri Pavlutin


Click “like” and then look, wechat search [Big Move the world] pay attention to this person without dACHang background, but with a positive attitude upward. In this paper, making github.com/qq449245884… Has been included, the article has been categorized, also organized a lot of my documentation, and tutorial materials.

Everyone said there was no project on your resume, so I found one and gave it away【 Construction tutorial 】.

Some features of JS have greatly changed the way we code. From ES6 onwards, the solutions, arrow functions, classes, and module systems for the features that most affect our code.

By August 2019, a new optional chain proposal has entered phase 3, which is a nice improvement. Optional linking changes the way properties are accessed from deep object structures.

Let’s see what this is about.

This week “big move the world” have lucky draw activity, prize: column “left ear hear the wind” X3, technology book X5, welcome to pay attention to reply: lucky draw

The problem

Due to the dynamic nature of JS, objects can have multiple layers of different nested object structures.

In general, when we deal with the following objects:

  • Get remote JSON data
  • Using configuration Objects
  • There are optional properties

Although JS supports different hierarchical data structures for objects, the complexity of accessing the properties of such objects increases.

BigObject can have different sets of properties at run time

Const bigObject = {//... prop1: { //... prop2: { // ... value: 'Some value' } } }; Const bigObject = {//... prop1: { // Nothing here } };Copy the code

Therefore, you must manually check whether the attribute exists

if (bigObject && bigObject.prop1 ! = null && bigObject.prop1.prop2 ! = null) { let result = bigObject.prop1.prop2.value; }Copy the code

It’s too long to write, so it’s best to avoid it.

Let’s look at how alternative chains solve this problem to reduce redundant code.

2. Easy to access properties in depth

Design an object that holds movie information. This object contains the required title property, as well as optional director and Actors.

The movieSmall object contains only title, while the movieFull object contains the full set of properties:

const movieSmall = {
  title: 'Heat'
};

const movieFull = {
  title: 'Blade Runner',
  director: { name: 'Ridley Scott' },
  actors: [{ name: 'Harrison Ford' }, { name: 'Rutger Hauer' }]
};
Copy the code

Write a function to get director. Remember, director may not exist.

function getDirector(movie) { if (movie.director ! = null) { return movie.director.name; } } getDirector(movieSmall); // => undefined getDirector(movieFull); // => 'Ridley Scott'Copy the code

If (movie.director) {… The} condition is used to verify that the director attribute is defined. Without this precaution, JS will raise TypeError: Cannot read property ‘name’ of undefined when accessing the movieSmall object’s director.

This scenario is best suited to using the optional chain feature, as shown below, and the code is much cleaner.

function getDirector(movie) { return movie.director? .name; } getDirector(movieSmall); // => undefined getDirector(movieFull); // => 'Ridley Scott'Copy the code

In the movie. The director? The optional link operator?. Is found in the.name expression.

In movieSmall, there is no director property. So, movie.director? The result of.name is undefined. The optional chain operator prevents TypeError: Cannot read property ‘name’ of undefined.

In a nutshell, the code snippet:

let name = movie.director? .name;Copy the code

Is equivalent to

let name; if (movie.director ! = null) { name = movie.director.name; }Copy the code

? Simplify the getDirector() function by eliminating two lines of code, which is why I like the optional chain.

Item 2.1 array

The optional chain feature can do much more. You are free to use multiple optional link operators in the same expression, and you can even use it to securely access array items.

The next task is to write a function that returns the name from the movie’s Actors.

In movie objects, the Actors array can be empty or even missing, so extra conditions must be added to null.

function getLeadingActor(movie) {
  if (movie.actors && movie.actors.length > 0) {
    return movie.actors[0].name;
  }
}

getLeadingActor(movieSmall); // => undefined
getLeadingActor(movieFull);  // => 'Harrison Ford'
Copy the code

if (movie.actors && movies.actors.length > 0) {… } Movie contains the actors property, and this property has at least one actor.

Using optional links, the code is also much cleaner, as follows:

function getLeadingActor(movie) { return movie.actors? [0]? .name; } getLeadingActor(movieSmall); // => undefined getLeadingActor(movieFull); // => 'Harrison Ford'Copy the code

actors? Ensure that the Actors attribute exists, [0]? . Make sure the first actor exists in the list.

3. Double question mark operator

A new proposal called Nullish Coalescing Operator? Handle undefined or NULL and default them to specific values.

Expression variable?? If the variable is undefined or null, the default value is the specified value.

const noValue = undefined;
const value = 'Hello';

noValue ?? 'Nothing'; // => 'Nothing'
value   ?? 'Nothing'; // => 'Hello'
Copy the code

Then use?? Optimize getLeading() to return “Unknown Actor” if there is no actor in the movie object.

function getLeadingActor(movie) { return movie.actors? [0]? .name ?? 'Unknown actor'; } getLeadingActor(movieSmall); // => 'Unknown actor' getLeadingActor(movieFull); // => 'Harrison Ford'Copy the code

4. Three forms of optional chain

We can use the following three forms of optional chains.

The first: Object? .property is used to access static properties:

const object = null; object? .property; // => undefinedCopy the code

The second kind: Object? .[expression] Is used to access dynamic properties or array items:

// one const object = null; const name = 'property'; object? .[name]; // => undefined // 2 const array = null; array? . [0]; // => undefinedCopy the code

The third: the object? .([arg1, [arg2,…]]) executes an object method

const object = null; object? .method('Some value'); // => undefinedCopy the code

Combine these three to create an optional chain:

const value = object.maybeUndefinedProp? .maybeNull()? .[propName];Copy the code

5. Short circuit: Encounterednull/undefinedstop

The interesting thing about the optional link operator is that as long as it’s on the left leftHandSide? .righthandSide if it encounters an invalid value, right access stops. This is called short-circuiting.

Take a look at some examples:

const nothing = null; let index = 0; nothing? .[index++]; // => undefined index; / / = > 0Copy the code

6. When to use the optional chain

Do not rush to use optional chain operators to access properties of any kind: this leads to incorrect use.

6.1 Accessing potentially invalid properties

? . Generally used in possibly empty attributes :maybeNullish? Prop. To ensure that the property is not empty, use the property accessor :.property or [propExpression].

Function logMovie(movie) {console.log(movie. Director? .name); console.log(movie.title); } function logMovie(movie) {// director needs optional chaining console.log(movie.director.name); // movie doesn't need optional chaining console.log(movie? .title); }Copy the code

6.2 There are usually better options

The following function hasPadding() receives a style object with an optional padding property. Padding has left, top, right, and bottom optional attributes.

Try using the optional chain operator:

function hasPadding({ padding }) { const top = padding? .top ?? 0; const right = padding? .right ?? 0; const bottom = padding? .bottom ?? 0; const left = padding? .left ?? 0; return left + top + right + bottom ! = = 0; } hasPadding({ color: 'black' }); // => false hasPadding({ padding: { left: 0 } }); // => false hasPadding({ padding: { right: 10 }}); // => trueCopy the code

Although the function correctly determines whether the element has padding, using an optional chain for each attribute is a bit too cumbersome.

A better approach is to use the object extension operator to default the padding object to zero

function hasPadding({ padding }) { const p = { top: 0, right: 0, bottom: 0, left: 0, ... padding }; return p.top + p.left + p.right + p.bottom ! = = 0; } hasPadding({ color: 'black' }); // => false hasPadding({ padding: { left: 0 } }); // => false hasPadding({ padding: { right: 10 }}); // => trueCopy the code

This is much cleaner than the alternative chain.

The bugs that may exist after code deployment cannot be known in real time. In order to solve these bugs, I spent a lot of time on log debugging. Incidentally, I recommend a good BUG monitoring tool for youFundebug.

Original text: dmitripavlutin.com/javascript-…

communication

This article is updated every week, you can search wechat “big move the world” for the first time to read and urge more (one or two earlier than the blog hey), this article GitHub github.com/qq449245884… It has been included and sorted out a lot of my documents. Welcome Star and perfect. You can refer to the examination points for review in the interview.