javascript new features

Let's look at some of the new features in javascript. This article will introduce their syntax and links to help readers keep abreast of their progress. We will demonstrate by writing a small test project how to quickly use these new features!

 Proposal

Proposal is divided into five stages. For more information, see the introduction documentation https://tc39.github.io/process-document/. Each proposal initially to "Sitelaoman" Stage 0 or leisure deer raised, at this stage, they are either not submitted to the technical committee, either not been rejected, but have not yet entered the next stage.

 As a personal recommendation, the reader should avoid the use of phase 0 is recommended in the unstable production environment.

The following proposals were not to enter Phase 0

Create a test project

Create a new directory and run the following command:

npm init -f

npm i [email protected] @babel/[email protected] @babel/[email protected] @babel/[email protected] @babel/[email protected] @babel/[email protected] @babel/[email protected] --save-dev`

Then add the following to the package.json file:

{

"scripts": {

"test": "ava"

},

"ava": {

"require": [

"@babel/register",

"@babel/polyfill"

]

}

}

Finally, create a .babelrc file:

{

"presets": [

[

"@babel/preset-env",

{

"targets": {

"node": "current"

}

}

],

"@babel/preset-stage-0"

],

"plugins": [

"@babel/plugin-transform-runtime"

]

}

Now you can start writing some test cases!

1. Optional operator
in JavaScript, we have been using the object, but sometimes is not what we expect of objects in the data structure. Here's what we suppose to get the desired data, may be obtained by calling the API to query the database.

const data = {

user: {

address: {

street: "Pennsylvania Avenue"

}

}

}

If the user does not have registered, you may get the following data:

const data = {

user: {}

};

When attempting to access the street in the following way, you will get an error:

console.log(data.user.address.street);

// Uncaught TypeError: Cannot read property 'street' of undefined

To avoid this, you need to access the "street" properties as follows:

const street = data && data.user && data.user.address && data.user.address.street;

console.log(street); // undefined`

In my opinion, this approach:

Unsightly

Onerous

Long-winded

If the optional operator can thus encoded:

console.log(data.user?.address?.street);

// undefined

So it looks more simple, and now we have seen the usefulness of this feature, and now to write a test!

import test from 'ava';

 

const valid = {

user: {

address: {

street: 'main street',

},

},

};

 

function getAddress(data) {

return data?.user?.address?.street;

}

 

test('Optional Chaining returns real values', (t) => {

const result = getAddress(valid);

t.is(result, 'main street');

});

We see the normal use of the optional sign, followed by a number of non-standard test data:

test('Optional chaining returns undefined for nullish properties.', (t) => {

t.is(getAddress(), undefined);

t.is(getAddress(null), undefined);

t.is(getAddress({}), undefined);

});

Example use for accessing the array elements:

const valid = {

user: {

address: {

street: 'main street',

neighbors: [

'john doe',

'Jane Doe'

],

},

},

};

 

function getNeighbor(data, number) {

return data?.user?.address?.neighbors?.[number];

}

 

test('Optional chaining works for array properties', (t) => {

t.is(getNeighbor(valid, 0), 'john doe');

});

 

test('Optional chaining returns undefined for invalid array properties', (t) => {

t.is(getNeighbor({}, 0), undefined);

});

Sometimes we do not know whether to implement a function in an object, a common scenario is that some older browsers may not have certain functions, we can use alternative operators access to detect whether the function has been achieved. Look at the following code:

const data = {

user: {

address: {

street: 'main street',

neighbors: [

'john doe',

'Jane Doe'

],

},

getNeighbors() {

return data.user.address.neighbors;

}

},

};

 

function getNeighbors(data) {

return data?.user?.getNeighbors?.();

}

 

test('Optional chaining also works with functions', (t) => {

const neighbors = getNeighbors(data);

t.is(neighbors.length, 2);

t.is(neighbors[0], 'john doe');

});

 

test('Optional chaining returns undefined if a function does not exist', (t) => {

const neighbors = getNeighbors({});

t.is(neighbors, undefined);

});

If the call chain is not complete, the function will not be executed, the logic behind it should look like this:

value == null ? value[some expression here]: undefined;

If, after an optional chain operator is undefined or null if nothing will execute, we can see the practical application of this rule in the following tests:

let neighborCount = 0;

 

function getNextNeighbor(neighbors) {

return neighbors?.[++neighborCount];

}

 

test('It short circuits expressions', (t) => {

const neighbors = getNeighbors(data);

t.is(getNextNeighbor(neighbors), 'jane doe');

t.is(getNextNeighbor(undefined), undefined);

t.is(neighborCount, 1);

});

With an optional transport operators, our code can be reduced if statement, lodash such as libraries and use && be chained calls.

2. merger null
Here are some common actions that we see in JavaScript:

Check for null or undefined

Set the default value to a variable

Ensuring 0, false, and '' is not set the default value

like this:

value != null ? value : 'default value';

Or this:

value || 'default value'

The problem is that, for the second implementation, at a value of 0, false and 'are considered false' time, so we must be clear to check for null and undefined.

value != null

Same as above:

value !== null && value !== undefined

That's where the new proposal, now we can do this:

value ?? 'default value';

This protects us is not 0, false, and 'set the default value, is not used and the ternary operator! Capture null and undefined case = null check.

Then write a simple test to verify how it works:

import test from 'ava';

 

test('Nullish coalescing defaults null', (t) => {

t.is(null ?? 'default', 'default');

});

 

test('Nullish coalescing defaults undefined', (t) => {

t.is(undefined ?? 'default', 'default');

});

 

test('Nullish coalescing defaults void 0', (t) => {

t.is(void 0 ?? 'default', 'default');

});

 

test('Nullish coalescing does not default 0', (t) => {

t.is(0 ?? 'default', 0);

});

 

test('Nullish coalescing does not default empty strings', (t) => {

t.is('' ?? 'default', '');

});

 

test('Nullish coalescing does not default false', (t) => {

t.is(false ?? 'default', false);

});

Seen in the test, set default values ​​for ?? null, undefined void and 0, is not 0, 'and the false set defaults.

3. The pipeline operator
in the programming function, we have a concept called Compose, which combined a plurality of function calls, an output from right to left performing each function, a receiving function before the function is invoked as its input, the following It is an example we discussed in pure JavaScript:

function doubleSay (str) {

return str + ", " + str;

}

 

function capitalize (str) {

return str[0].toUpperCase() + str.substring(1);

}

 

function exclaim (str) {

return str + '!';

}

 

let result = exclaim(capitalize(doubleSay("hello")));

result //=> "Hello, hello!"

The combined use of this function is very common common way that most of the functionality that the library, such as lodash and ramda have achieved.

Using the new pipeline operator may not use the third-party libraries shown above press written as follows:

let result = "hello"

|> doubleSay

|> capitalize

|> exclaim;

result //=> "Hello, hello!"`

This proposal aims to make the call chain function more readable, in conjunction with the next part of the application function also works well, use something like this:

let result = 1

|> (_ => Math.max(0, _));

result //=> 1

let result = -5

|> (_ => Math.max(0, _));

result //=> 0

Write test cases as follows:

import test from 'ava';

 

function doubleSay (str) {

return str + ", " + str;

}

 

function capitalize (str) {

return str[0].toUpperCase() + str.substring(1);

}

 

function exclaim (str) {

return str + '!';

}

 

test('Simple pipeline usage', (t) => {

let result = "hello"

|> doubleSay

|> capitalize

|> exclaim;

 

t.is(result, 'Hello, hello!');

});

 

test('Partial application pipeline', (t) => {

let result = -5

|> (_ => Math.max(0, _));

 

t.is(result, 0);

});

 

test('Async pipeline', async (t) => {

const asyncAdd = (number) => Promise.resolve(number + 5);

const subtractOne = (num1) => num1 - 1;

const result = 10

|> asyncAdd

|> (async (num) => subtractOne(await num));

 

t.is(await result, 14);

});

Note that, once added to the pipe async function, must await the return value, the return value is because the promise. There is a proposal to start support |> await asyncFunction, but not yet implemented.

Finally, since you have seen the practical application of these proposals, I hope you try these proposals!

Guess you like

Origin www.cnblogs.com/blogst/p/11781259.html