ES6 JavaScript Object Literals

The material, the translation of which we present to your attention, is devoted to the study of the features of object literals in JavaScript, in particular, innovations that have appeared in recent versions of the ECMAScript standard.

JavaScript has the power and convenience of creating objects using object literals. The ES2015 (ES6) standard simplifies working with objects when creating applications for modern browsers (except IE) and for the Node.js platform.



The basics


Creating objects in some languages ​​can be expensive, by which we mean both the programmer’s working time and the computing resources of the systems. In particular, we are talking about the fact that, before creating objects, it is necessary to describe classes (for example, using the class keyword). In JavaScript, objects can be created very quickly and easily, without the need to perform any preliminary actions. Consider an example:

 // ES5 var myObject = { prop1: 'hello', prop2: 'world', output: function() {   console.log(this.prop1 + ' ' + this.prop2); } }; myObject.output(); // hello world 

In programming, “disposable” objects are often used. They store settings and other data, they are used as parameters of functions, as values ​​returned by functions, and in other situations. JavaScript object literals in such cases are very helpful, and ES6 expands their capabilities.

Initializing objects from variables


Properties of objects are often created from variables, assigning to them the same names that are already assigned to these variables. For example:

 // ES5 var a = 1, b = 2, c = 3; obj = {   a: a,   b: b,   c: c }; // obj.a = 1, obj.b = 2, obj.c = 3 

In ES6, you no longer need to repeat variable names:

 // ES6 const a = 1, b = 2, c = 3; obj = {   a,   b,   c }; // obj.a = 1, obj.b = 2, obj.c = 3 

This technique can be useful for returned objects using the Revealing Module pattern, which allows you to create namespaces for different code fragments in order to avoid name conflicts. For example:

 // ES6 const lib = (() => { function sum(a, b)  { return a + b; } function mult(a, b) { return a * b; } return {   sum,   mult }; }()); console.log( lib.sum(2, 3) );  // 5 console.log( lib.mult(2, 3) ); // 6 

You may have seen how this technique is used in ES6 modules:

 // lib.js function sum(a, b)  { return a + b; } function mult(a, b) { return a * b; } export { sum, mult }; 

Short syntax for declaring object methods


When declaring object methods in ES5, you must use the function keyword:

 // ES5 var lib = { sum:  function(a, b) { return a + b; }, mult: function(a, b) { return a * b; } }; console.log( lib.sum(2, 3) );  // 5 console.log( lib.mult(2, 3) ); // 6 

Now, in ES6, this can no longer be done. Here we have the following abbreviated method of declaring methods:

 // ES6 const lib = { sum(a, b)  { return a + b; }, mult(a, b) { return a * b; } }; console.log( lib.sum(2, 3) );  // 5 console.log( lib.mult(2, 3) ); // 6 

It should be noted that ES6 ( => ) arrow functions cannot be used here, since the methods must have names. However, the arrow functions can be used if you explicitly assign names to methods (as in ES5). For example:

 // ES6 const lib = { sum:  (a, b) => a + b, mult: (a, b) => a * b }; console.log( lib.sum(2, 3) );  // 5 console.log( lib.mult(2, 3) ); // 6 

Dynamic keys


In ES5, it was impossible to use variables as key names, although a key whose name is given to a variable could be added after the object was created. For example:

 // ES5 var key1 = 'one', obj = {   two: 2,   three: 3 }; obj[key1] = 1; // obj.one = 1, obj.two = 2, obj.three = 3 

In ES6, keys can be assigned dynamically by putting an expression that defines the name in square brackets ( [] ). For example:

 // ES6 const key1 = 'one', obj = {   [key1]: 1,   two: 2,   three: 3 }; // obj.one = 1, obj.two = 2, obj.three = 3 

To create a key, you can use any expression:

 // ES6 const i = 1, obj = {   ['i' + i]: i }; console.log(obj.i1); // 1 

Dynamic keys can be used for both methods and properties:

 // ES6 const i = 2, obj = {   ['mult' + i]: x => x * i }; console.log( obj.mult2(5) ); // 10 

Another question is whether it is necessary to create properties and methods with dynamically generated names. The readability of the code in which this technique is used may deteriorate. Perhaps if you are faced with situations in which dynamic names seem appropriate, it would be better to think about using factory functions or classes to create objects.

Destructuring


Destructuring is the extraction of properties of objects and assigning them to variables. Often during the development of applications, it is necessary to extract the value of an object property and write it into a variable. In ES5, it was necessary to describe this as follows, using property access commands:

 // ES5 var myObject = { one:   'a', two:   'b', three: 'c' }; var one   = myObject.one, // 'a' two   = myObject.two, // 'b' three = myObject.three; // 'c' 

ES6 supports destructuring. You can create a variable with the same name as the corresponding property of the object and do the following:

 // ES6 const myObject = { one:   'a', two:   'b', three: 'c' }; const { one, two, three } = myObject; // one = 'a', two = 'b', three = 'c' 

Variables in which the property values ​​of an object can actually have any names, but if they differ from the property names, you must use the { propertyName: newVariable } :

 // ES6 const myObject = { one:   'a', two:   'b', three: 'c' }; const { one: first, two: second, three: third } = myObject; // first = 'a', second = 'b', third = 'c' 

Objects with a complex structure, in which arrays and other objects are nested, can also be used in destructive assignment operations:

 // ES6 const meta = { title: 'Enhanced Object Literals', pageinfo: {   url: 'https://www.sitepoint.com/',   description: 'How to use object literals in ES2015 (ES6).',   keywords: 'javascript, object, literal' } }; const { title   : doc, pageinfo: { keywords: topic } } = meta; /* doc   = 'Enhanced Object Literals' topic = 'javascript, object, literal' */ 

At first, all this may seem complicated, however, it is not so difficult to understand this, the main thing is to remember the following:


When using restructuring, you may encounter some difficulties. Thus, an expression cannot be started with a curly bracket, since then it will look like a block of code. For example:

 { a, b, c } = myObject; //  

This construction is normally perceived by the system when declaring variables:

 const { a, b, c } = myObject; //  

If the variables are already declared, you must enclose the expression in parentheses:

 let a, b, c; ({ a, b, c } = myObject); //  

As a result, while dealing with destructuring, one should be attentive to the code and not mix the declared and undeclared variables.

Destructuring is a technique that can be useful in many situations.

Default Function Parameters


If a function needs a long list of arguments, it is usually easier to pass one object with parameters to it. For example:

 prettyPrint( { title: 'Enhanced Object Literals', publisher: {   name: 'SitePoint',   url: 'https://www.sitepoint.com/' } } ); 

In ES5, it was necessary to disassemble objects with parameters in order, if such objects do not contain what is needed, assign default values ​​to the corresponding parameters:

 // ES5,     function prettyPrint(param) { param = param || {}; var   pubTitle = param.title || 'No title',   pubName = (param.publisher && param.publisher.name) || 'No publisher'; return pubTitle + ', ' + pubName; } 

In ES6, any parameters can be assigned default values:

 // ES6 -     function prettyPrint(param = {}) { ... } 

You can then use restructuring to extract values ​​from the object, and, if necessary, to assign default values:

 // ES6     function prettyPrint( {   title: pubTitle = 'No title',   publisher: { name: pubName = 'No publisher' } } = {} ) { return `${pubTitle}, ${pubName}`; } 

It is worth noting that such code may be harder to read than the more traditional one, although this is a matter of the programmer’s personal bias.

Parsing objects returned by functions


Functions can return only one value, but this value can be an object with hundreds of properties or methods. In ES5, it was necessary to first get the returned object, and after that it was possible to extract values ​​from it:

 // ES5 var obj = getObject(), one = obj.one, two = obj.two, three = obj.three; 

Destructuring simplifies this process. Now all this can be done without having to save the object in a separate variable and then parse it:

 // ES6 const { one, two, three } = getObject(); 

You may have seen something similar in the programs for Node.js. For example, if you need only the readFile() and writeFile() methods of the fs module, you can get links to them like this:

 // ES6 Node.js const { readFile, writeFile } = require('fs'); readFile('file.txt', (err, data) => { console.log(err || data); }); writeFile('new.txt', 'new content', err => { console.log(err || 'file written'); }); 

Syntax of the remaining parameters and the ES2018 extension operator (ES9)


= In ES2015, the syntax of the remaining parameters and the extension operator (both of which look like three dots, ) were used only when working with arrays. In ES2018, similar functionality can be used to work with objects:

 const myObject = { a: 1, b: 2, c: 3 }; const { a, ...x } = myObject; // a = 1 // x = { b: 2, c: 3 } 

A similar approach can be used to transfer some values ​​to the function:

 function restParam({ a, ...x }) { // a = 1 // x = { b: 2, c: 3 } } restParam({ a: 1, b: 2, c: 3 }); 

Note that in such situations you can use only one expression with three dots at the end of the list. In addition, for objects embedded in other objects, this does not work.

The extension operator can be used inside objects:

 const obj1 = { a: 1, b: 2, c: 3 }, obj2 = { ...obj1, z: 26 }; // obj2 is { a: 1, b: 2, c: 3, z: 26 } 

The extension operator can be used for cloning objects ( obj2 = { ...obj1 }; ), but here we must take into account the fact that this approach makes a small copy of the object. If the properties of the objects are other objects, the clone of the object will refer to the same nested objects.

The syntax of the remaining parameters and the extension operator still have not very broad support. At the moment, they, without additional efforts, can be used in Chrome and Firefox browsers, and when developing for the Node.js platform version 8.6 and higher.

Results


Object literals have always been a useful JavaScript feature. Innovations that appear in JavaScript starting with the ES2015 standard do not carry fundamental changes, but they save the programmer’s time and help to write cleaner and more concise code.

Dear readers! What methods of creating JS-objects do you use most often?

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


All Articles